head	1.26;
access;
symbols
	Version_2_1:1.15
	no_dilllon_crap:1.5
	C_Demo_1:1.4;
locks; strict;
comment	@ * @;


1.26
date	92.07.30.19.51.20;	author mer;	state Exp;
branches;
next	1.25;

1.25
date	92.05.28.21.11.58;	author mer;	state Exp;
branches;
next	1.24;

1.24
date	92.03.11.02.17.16;	author mer;	state Exp;
branches;
next	1.23;

1.23
date	91.11.21.15.45.36;	author mer;	state Exp;
branches;
next	1.22;

1.22
date	91.11.14.19.39.41;	author kemnitz;	state Exp;
branches;
next	1.21;

1.21
date	91.09.05.23.28.36;	author hong;	state Exp;
branches;
next	1.20;

1.20
date	91.08.29.23.54.07;	author mer;	state Exp;
branches;
next	1.19;

1.19
date	91.08.14.22.10.42;	author mer;	state Exp;
branches;
next	1.18;

1.18
date	91.07.22.14.20.32;	author mer;	state Exp;
branches;
next	1.17;

1.17
date	91.06.10.20.57.51;	author kemnitz;	state Exp;
branches;
next	1.16;

1.16
date	91.04.01.08.47.28;	author hong;	state Exp;
branches;
next	1.15;

1.15
date	90.11.12.08.16.01;	author hong;	state Exp;
branches;
next	1.14;

1.14
date	90.10.16.23.33.27;	author hong;	state Exp;
branches;
next	1.13;

1.13
date	90.09.30.14.41.26;	author goh;	state Exp;
branches;
next	1.12;

1.12
date	90.09.30.14.17.53;	author goh;	state Exp;
branches;
next	1.11;

1.11
date	90.09.30.13.58.49;	author goh;	state Exp;
branches;
next	1.10;

1.10
date	90.09.25.16.44.46;	author kemnitz;	state Exp;
branches;
next	1.9;

1.9
date	90.04.19.16.38.23;	author kemnitz;	state Exp;
branches;
next	1.8;

1.8
date	90.03.31.19.12.45;	author cimarron;	state Exp;
branches;
next	1.7;

1.7
date	90.02.12.21.44.01;	author kemnitz;	state Exp;
branches;
next	1.6;

1.6
date	90.02.12.19.48.18;	author cimarron;	state Exp;
branches;
next	1.5;

1.5
date	90.02.01.17.39.27;	author goh;	state Exp;
branches;
next	1.4;

1.4
date	89.09.05.17.23.47;	author mao;	state C_Demo_1;
branches;
next	1.3;

1.3
date	89.08.03.00.06.24;	author dillon;	state Exp;
branches;
next	1.2;

1.2
date	89.02.02.16.16.05;	author dillon;	state Stab;
branches;
next	1.1;

1.1
date	89.01.17.05.57.21;	author cimarron;	state Exp;
branches;
next	;


desc
@@


1.26
log
@acquire a spinlock during inval shm buffer initialization
@
text
@/* ----------------------------------------------------------------
 *   FILE
 * 	sinvaladt.c
 *	
 *   DESCRIPTION
 *	POSTGRES shared cache invalidation segment definitions.
 *
 *   INTERFACE ROUTINES
 *
 *   NOTES
 *
 *   IDENTIFICATION
 *	$Header: /private/mer/pg/src/storage/ipc/RCS/sinvaladt.c,v 1.25 1992/05/28 21:11:58 mer Exp mer $
 * ----------------------------------------------------------------
 */

/* ----------------
 *	include files
 *
 *	XXX yucky order dependency
 * ----------------
 */

#include "storage/ipci.h"
#include "storage/ipc.h"
#include "storage/sinvaladt.h"
#include "storage/lmgr.h"
#include "utils/log.h"

/* ----------------
 *	global variable notes
 *
 *	SharedInvalidationSemaphore
 *
 *	shmInvalBuffer
 *		the shared buffer segment, set by SISegmentAttach()
 *
 *	MyBackendId
 *		might be removed later, used only for
 * 		debugging in debug routines (end of file)
 *
 *	SIDbId
 *		identification of buffer (disappears)
 *
 *	SIRelId		\ 
 *	SIDummyOid	 \  identification of buffer
 *	SIXidData	 /
 *	SIXid		/
 *
 *  XXX This file really needs to be cleaned up.  We switched to using
 *	spinlocks to protect critical sections (as opposed to using fake
 *	relations and going through the lock manager) and some of the old
 *	cruft was 'ifdef'ed out, while other parts (now unused) are still
 *	compiled into the system. -mer 5/24/92
 * ----------------
 */
#ifdef HAS_TEST_AND_SET
int SharedInvalidationLockId;
#else
IpcSemaphoreId	SharedInvalidationSemaphore;
#endif
SISeg		*shmInvalBuffer;	
extern BackendId MyBackendId;

OID 		SIDbId = 0;	    
LRelId  	SIRelId;    	    
OID 		SIDummyOid = InvalidObjectId;

#ifdef _FOO_BAR_BAZ_
/*
 * XXX this won't work now with 4 byte xid's it should probably be torched.
 */
TransactionIdData	SIXidData;
TransactionId		SIXid = &SIXidData;
#endif

/* ----------------
 *	declarations
 * ----------------
 */

/*
 * SISetActiveProcess --
 */
extern
BackendId
SIAssignBackendId ARGS((
	SISeg 		*segInOutP,
	BackendTag	tag
));

/*
 * CleanupInvalidationState --
 * Note:
 *	This is a temporary hack.  ExitBackend should call this instead
 *	of exit (via on_exitpg).
 */
extern
void
CleanupInvalidationState ARGS((
	int		status,	/* XXX */
	SISeg		*segInOutP
));

/************************************************************************/
/* SISetActiveProcess(segP, backendId)	set the backend status active	*/
/*  	should be called only by the postmaster when creating a backend	*/
/************************************************************************/
/* XXX I suspect that the segP parameter is extraneous. -hirohama */
void
SISetActiveProcess(segInOutP, backendId)
    SISeg 	*segInOutP;
    BackendId 	backendId;
{
    /* mark all messages as read */

    /* Assert(segP->procState[backendId - 1].tag == MyBackendTag); */

    segInOutP->procState[backendId - 1].resetState = false;
    segInOutP->procState[backendId - 1].limit = SIGetNumEntries(segInOutP);
}

/****************************************************************************/
/* SIBackendInit()  initializes a backend to operate on the buffer  	    */
/****************************************************************************/
int
SIBackendInit(segInOutP)
    SISeg 		*segInOutP;
{
    LRelId  	    	    LtCreateRelId();
    TransactionId           LMITransactionIdCopy();
    
    Assert(MyBackendTag > 0);

    MyBackendId = SIAssignBackendId(segInOutP, MyBackendTag);
    if (MyBackendId == InvalidBackendTag)
	return 0;

#ifdef	INVALIDDEBUG
    elog(DEBUG, "SIBackendInit: backend tag %d; backend id %d.",
	 MyBackendTag, MyBackendId);
#endif	INVALIDDEBUG

    SISetActiveProcess(segInOutP, MyBackendId);
    on_exitpg(CleanupInvalidationState, segInOutP);
    return 1;
}

/* ----------------
 *	SIAssignBackendId
 * ----------------
 */
BackendId
SIAssignBackendId(segInOutP, backendTag)
    SISeg		*segInOutP;
    BackendTag	backendTag;
{
    Index		index;
    ProcState	*stateP;

    stateP = NULL;

    for (index = 0; index < MaxBackendId; index += 1) {
	if (segInOutP->procState[index].tag == InvalidBackendTag ||
	    segInOutP->procState[index].tag == backendTag)
	    {
		stateP = &segInOutP->procState[index];
		break;
	    }

	if (!PointerIsValid(stateP) ||
	    (segInOutP->procState[index].resetState &&
	     (!stateP->resetState ||
	      stateP->tag < backendTag)) ||
	    (!stateP->resetState &&
	     (segInOutP->procState[index].limit <
	      stateP->limit ||
	      stateP->tag < backendTag)))
	    {
		stateP = &segInOutP->procState[index];
	    }
    }

    /* verify that all "procState" entries checked for matching tags */

    for (index += 1; index < MaxBackendId; index += 1) {
	if (segInOutP->procState[index].tag == backendTag) {
	    elog (FATAL, "SIAssignBackendId: tag %d found twice",
		  backendTag);
	}
    }

    if (stateP->tag != InvalidBackendTag) {
	if (stateP->tag == backendTag) {
	    elog(NOTICE, "SIAssignBackendId: reusing tag %d",
		 backendTag);
	} else {
	    elog(NOTICE,
		 "SIAssignBackendId: discarding tag %d",
		 stateP->tag);
	    return InvalidBackendTag;
	}
    }

    stateP->tag = backendTag;

    return (1 + stateP - &segInOutP->procState[0]);
}


/************************************************************************/
/* The following function should be called only by the postmaster !!    */
/************************************************************************/

/************************************************************************/
/* SISetDeadProcess(segP, backendId)  set the backend status DEAD   	*/
/*  	should be called only by the postmaster when a backend died 	*/
/************************************************************************/
void
SISetDeadProcess(segP, backendId)
    SISeg 	*segP;
    int 	backendId;
{
    /* XXX call me.... */

    segP->procState[backendId - 1].resetState = false;
    segP->procState[backendId - 1].limit = -1;
    segP->procState[backendId - 1].tag = InvalidBackendTag;
}

/* ----------------
 *	CleanupInvalidationState
 * ----------------
 */
void
CleanupInvalidationState(status, segInOutP)
    int		status;		/* XXX */
    SISeg	*segInOutP;	/* XXX style */
{
    Assert(PointerIsValid(segInOutP));

    SISetDeadProcess(segInOutP, MyBackendId);
}


/************************************************************************/
/* SIComputeSize()  - retuns the size of a buffer segment   	    	*/
/************************************************************************/
SISegOffsets *
SIComputeSize(segSize)
    int *segSize;
{
    int      	 A, B, a, b, totalSize;
    SISegOffsets *oP;

    A = 0;
    a = SizeSISeg;  	/* offset to first data entry */
    b = SizeOfOneSISegEntry * MAXNUMMESSAGES;
    B = A + a + b;
    totalSize = B - A;
    *segSize = totalSize;
    
    oP = (SISegOffsets *) palloc(sizeof(SISegOffsets));
    oP->startSegment = A;
    oP->offsetToFirstEntry = a; /* relatiove to A */
    oP->offsetToEndOfSegemnt = totalSize; /* relative to A */
    return(oP);
}


/************************************************************************/
/* SIGetSemaphoreId - returns the general semaphore Id	    	    	*/
/************************************************************************/
SIGetSemaphoreId(segP)
    SISeg *segP;
{
    return(segP->generalSemaphoreId);
}


/************************************************************************/
/* SISetSemaphoreId 	- sets the general semaphore Id	    	    	*/
/************************************************************************/
void
SISetSemaphoreId(segP, id)
    SISeg *segP;
    IpcSemaphoreId id;
{
    segP->generalSemaphoreId = id;
}


/************************************************************************/
/* SISetStartEntrySection(segP, offset)     - sets the offset		*/
/************************************************************************/
void
SISetStartEntrySection(segP, offset)
    SISeg *segP;
    Offset offset;
{
    segP->startEntrySection = offset;
}

/************************************************************************/
/* SIGetStartEntrySection(segP)     - returnss the offset   		*/
/************************************************************************/
Offset
SIGetStartEntrySection(segP)
SISeg *segP;
{
    return(segP->startEntrySection);
}


/************************************************************************/
/* SISetEndEntrySection(segP, offset) 	- sets the offset   		*/
/************************************************************************/
void
SISetEndEntrySection(segP, offset)
    SISeg *segP;
    Offset offset;
{
    segP->endEntrySection = offset;
}

/************************************************************************/
/* SIGetEndEntrySection(segP) 	- returnss the offset	    	    	*/
/************************************************************************/
Offset
SIGetEndEntrySection(segP)
    SISeg *segP;
{
    return(segP->endEntrySection);
}

/************************************************************************/
/* SISetEndEntryChain(segP, offset) 	- sets the offset   	    	*/
/************************************************************************/
void
SISetEndEntryChain(segP, offset)
    SISeg *segP;
    Offset offset;
{
    segP->endEntryChain = offset;
}

/************************************************************************/
/* SIGetEndEntryChain(segP) 	- returnss the offset	    	    	*/
/************************************************************************/
Offset
SIGetEndEntryChain(segP)
    SISeg *segP;
{
    return(segP->endEntryChain);
}

/************************************************************************/
/* SISetStartEntryChain(segP, offset) 	- sets the offset   	    	*/
/************************************************************************/
void
SISetStartEntryChain(segP, offset)
    SISeg *segP;
    Offset offset;
{
    segP->startEntryChain = offset;
}

/************************************************************************/
/* SIGetStartEntryChain(segP) 	- returns  the offset	    	    	*/
/************************************************************************/
Offset
SIGetStartEntryChain(segP)
    SISeg *segP;
{
    return(segP->startEntryChain);
}

/************************************************************************/
/* SISetNumEntries(segP, num)	sets the current nuber of entries   	*/
/************************************************************************/
bool
SISetNumEntries(segP, num)
    SISeg *segP;
    int   num;
{
    if ( num <= MAXNUMMESSAGES) {
        segP->numEntries =  num;
        return(true);
    } else {
        return(false);  /* table full */
    }    
}

/************************************************************************/
/* SIGetNumEntries(segP)    - returns the current nuber of entries  	*/
/************************************************************************/
int
SIGetNumEntries(segP)
    SISeg *segP;
{
    return(segP->numEntries);
}


/************************************************************************/
/* SISetMaxNumEntries(segP, num)    sets the maximal number of entries	*/
/************************************************************************/
bool
SISetMaxNumEntries(segP, num)
    SISeg *segP;
    int   num;
{
    if ( num <= MAXNUMMESSAGES) {
        segP->maxNumEntries =  num;
        return(true);
    } else {
        return(false);  /* wrong number */
    }   
}


/************************************************************************/
/* SIGetMaxNumEntries(segP) 	returns the maximal number of entries	*/
/************************************************************************/
int
SIGetMaxNumEntries(segP)
    SISeg *segP;
{
    return(segP->maxNumEntries);
}

/************************************************************************/
/* SIGetProcStateLimit(segP, i)	returns the limit of read messages  	*/
/************************************************************************/
int
SIGetProcStateLimit(segP, i) 
    SISeg 	*segP;
    int 	i;
{
    return(segP->procState[i].limit);
}

/************************************************************************/
/* SIGetProcStateResetState(segP, i)  returns the limit of read messages*/
/************************************************************************/
bool
SIGetProcStateResetState(segP, i) 
    SISeg 	*segP;
    int 	i;
{
    return((bool) segP->procState[i].resetState);
}

/************************************************************************/
/* SIIncNumEntries(segP, num)	increments the current nuber of entries	*/
/************************************************************************/
bool
SIIncNumEntries(segP, num)
    SISeg *segP;
    int   num;
{
    if ((segP->numEntries + num) <= MAXNUMMESSAGES) {
        segP->numEntries = segP->numEntries + num;
        return(true);
    } else {
        return(false);  /* table full */
    }   
}

/************************************************************************/
/* SIDecNumEntries(segP, num)	decrements the current nuber of entries	*/
/************************************************************************/
bool
SIDecNumEntries(segP, num)
    SISeg *segP;
    int   num;
{
    if ((segP->numEntries - num) >=  0) {
        segP->numEntries = segP->numEntries - num;
        return(true);
    } else {
        return(false);  /* not enough entries in table */
    }   
}

/************************************************************************/
/* SISetStartFreeSpace(segP, offset)  - sets the offset	    	    	*/
/************************************************************************/
void
SISetStartFreeSpace(segP, offset)
    SISeg *segP;
    Offset offset;
{
    segP->startFreeSpace = offset;
}

/************************************************************************/
/* SIGetStartFreeSpace(segP)  - returns the offset  	    	    	*/
/************************************************************************/
Offset
SIGetStartFreeSpace(segP)
    SISeg *segP;
{
    return(segP->startFreeSpace);
}



/************************************************************************/
/* SIGetFirstDataEntry(segP)  returns first data entry	    	    	*/
/************************************************************************/
SISegEntry *
SIGetFirstDataEntry(segP)
    SISeg *segP;
{
    SISegEntry  *eP;
    Offset      startChain;
    
    startChain = SIGetStartEntryChain(segP);
    
    if (startChain == InvalidOffset)
    	return(NULL);
    	 
    eP = (SISegEntry  *) ((Pointer) segP + 
                           SIGetStartEntrySection(segP) +
                           startChain );
    return(eP);
}


/************************************************************************/
/* SIGetLastDataEntry(segP)  returns last data entry in the chain   	*/
/************************************************************************/
SISegEntry *
SIGetLastDataEntry(segP)
    SISeg *segP;
{
    SISegEntry  *eP;
    Offset      endChain;
    
    endChain = SIGetEndEntryChain(segP);
    
    if (endChain == InvalidOffset)
    	return(NULL);
    	 
    eP = (SISegEntry  *) ((Pointer) segP + 
                           SIGetStartEntrySection(segP) +
                           endChain );
    return(eP);
}

/************************************************************************/
/* SIGetNextDataEntry(segP, offset)  returns next data entry	    	*/
/************************************************************************/
SISegEntry *
SIGetNextDataEntry(segP, offset)
    SISeg 	    *segP;
    Offset       offset;
{
    SISegEntry  *eP;
    
    if (offset == InvalidOffset)
    	return(NULL);
    	
    eP = (SISegEntry  *) ((Pointer) segP +
                          SIGetStartEntrySection(segP) + 
                          offset);
    return(eP);
}


/************************************************************************/
/* SIGetNthDataEntry(segP, n)	returns the n-th data entry in chain	*/
/************************************************************************/
SISegEntry *
SIGetNthDataEntry(segP, n)
    SISeg 	*segP;
    int 	n;      /* must range from 1 to MaxMessages */
{
    SISegEntry  *eP;
    int	    	i;
    
    if (n <= 0) return(NULL);
    
    eP = SIGetFirstDataEntry(segP);
    for (i = 1; i < n; i++) {
    	/* skip one and get the next	*/
    	eP = SIGetNextDataEntry(segP, eP->next);
    }
    
    return(eP);
}

/************************************************************************/
/* SIEntryOffset(segP, entryP)   returns the offset for an pointer  	*/
/************************************************************************/
Offset
SIEntryOffset(segP, entryP)
    SISeg  	*segP;
    SISegEntry *entryP;
{
    /* relative to B !! */
    return ((Offset) ((Pointer) entryP -
                      (Pointer) segP - 
                      SIGetStartEntrySection(segP) ));
}


/************************************************************************/
/* SISetDataEntry(segP, data)  - sets a message in the segemnt	    	*/
/************************************************************************/
bool
SISetDataEntry(segP, data)
    SISeg *segP;
    SharedInvalidData  *data;
{
    Offset  	    offsetToNewData;
    SISegEntry 	    *eP, *lastP;
    bool    	    SISegFull();
    Offset  	    SIEntryOffset();
    Offset  	    SIGetStartFreeSpace();
    SISegEntry 	    *SIGetFirstDataEntry();
    SISegEntry 	    *SIGetNextDataEntry();
    SISegEntry 	    *SIGetLastDataEntry();

    if (!SIIncNumEntries(segP, 1)) 
      return(false);  /* no space */
    
    /* get a free entry */
    offsetToNewData = SIGetStartFreeSpace(segP);
    eP = SIGetNextDataEntry(segP, offsetToNewData); /* it's a free one */
    SISetStartFreeSpace(segP, eP->next);
    /* fill it up */
    eP->entryData = *data;
    eP->isfree = false;
    eP->next = InvalidOffset;
    
    /* handle insertion point at the end of the chain !!*/
    lastP = SIGetLastDataEntry(segP);
    if (lastP == NULL) {
    	/* there is no chain, insert the first entry */
    	SISetStartEntryChain(segP, SIEntryOffset(segP, eP));
    } else {
    	/* there is a last entry in the chain */
    	lastP->next = SIEntryOffset(segP, eP);
    }
    SISetEndEntryChain(segP, SIEntryOffset(segP, eP));
    return(true);
}


/************************************************************************/
/* SIDecProcLimit(segP, num)  decrements all process limits 	    	*/
/************************************************************************/
void
SIDecProcLimit(segP, num)
    SISeg 	*segP;
    int 	num;
{
    int i;
    for (i=0; i < MaxBackendId; i++) {
    	/* decrement only, if there is a limit > 0  */
    	if (segP->procState[i].limit > 0) {
    	    segP->procState[i].limit = segP->procState[i].limit - num;
    	    if (segP->procState[i].limit < 0) {
    	    	/* limit was not high enough, reset to zero */
    	    	/* negative means it's a dead backend	    */
    	    	segP->procState[i].limit = 0;
    	    }
    	}
    }
}
 

/************************************************************************/
/* SIDelDataEntry(segP)	    - free the FIRST entry   	    	    	*/
/************************************************************************/
bool
SIDelDataEntry(segP)
    SISeg 	*segP;
{
    SISegEntry 	    *eP, *e1P;
    SISegEntry 	    *SIGetFirstDataEntry();

    if (!SIDecNumEntries(segP, 1))  {
    	/* no entries in buffer */
    	return(false);
    }
    
    e1P = SIGetFirstDataEntry(segP);
    SISetStartEntryChain(segP, e1P->next);
    if (SIGetStartEntryChain(segP) == InvalidOffset) {
    	/* it was the last entry */
    	SISetEndEntryChain(segP, InvalidOffset);
    }
    /* free the entry */
    e1P->isfree = true;
    e1P->next = SIGetStartFreeSpace(segP);
    SISetStartFreeSpace(segP, SIEntryOffset(segP, e1P));
    SIDecProcLimit(segP, 1);
    return(true); 
}

    

/************************************************************************/
/* SISetProcStateInvalid(segP)	checks and marks a backends state as 	*/
/*  	    	    	    	    invalid 	    	    	    	*/
/************************************************************************/
void
SISetProcStateInvalid(segP)
    SISeg 	*segP;
{
    int i;

    for (i=0; i < MaxBackendId; i++) {
    	if (segP->procState[i].limit == 0) {
    	    /* backend i didn't read any message    	    	    	*/
    	    segP->procState[i].resetState = true;
    	    /*XXX signal backend that it has to reset its internal cache ? */
    	}
    }
}

/************************************************************************/
/* SIReadEntryData(segP, backendId, function)	    	    	    	*/
/*  	    	    	- marks messages to be read by id   	    	*/
/*  	    	          and executes function	    	    	    	*/
/************************************************************************/
void
SIReadEntryData(segP, backendId, invalFunction, resetFunction)
    SISeg   *segP;
    int     backendId;
    void    (*invalFunction)();
    void    (*resetFunction)();
{
    int i;
    SISegEntry *data;

    Assert(segP->procState[backendId - 1].tag == MyBackendTag);

    if (!segP->procState[backendId - 1].resetState) {
    	/* invalidate data, but only those, you have not seen yet !!*/
    	/* therefore skip read messages */
    	i = 0;
    	data = SIGetNthDataEntry(segP, 
    	    	    	    	 SIGetProcStateLimit(segP, backendId - 1) + 1);
    	while (data != NULL) {
    	    i++;
    	    segP->procState[backendId - 1].limit++;  /* one more message read */
    	    invalFunction(data->entryData.cacheId, 
    	         data->entryData.hashIndex,
    	         &data->entryData.pointerData);
    	    data = SIGetNextDataEntry(segP, data->next);
    	}
    	/* SIDelExpiredDataEntries(segP); */
    } else {
    	/*backend must not read messages, its own state has to be reset	    */
    	elog(NOTICE, "SIMarkEntryData: cache state reset");
        resetFunction(); /* XXXX call it here, parameters? */

		/* new valid state--mark all messages "read" */
		segP->procState[backendId - 1].resetState = false;
		segP->procState[backendId - 1].limit = SIGetNumEntries(segP);
    }
    /* check whether we can remove dead messages    	    	    	    */
    if (i > MAXNUMMESSAGES) {
    	elog(FATAL, "SIReadEntryData: Invalid segment state");
    }
}

/************************************************************************/
/* SIDelExpiredDataEntries  (segP)  - removes irrelevant messages   	*/
/************************************************************************/
void
SIDelExpiredDataEntries(segP)
    SISeg 	*segP;
{
    int   min, i, h;
    
    min = 9999999;
    for (i = 0; i < MaxBackendId; i++) {
    	h = SIGetProcStateLimit(segP, i);
    	if (h >= 0)  { /* backend active */
    	    if (h < min ) min = h;
    	}
    }
    if (min != 9999999) {
    	/* we can remove min messages */
    	for (i = 1; i <= min; i++) {
    	    /* this  adjusts also the state limits!*/
    	    if (!SIDelDataEntry(segP)) { 
            	elog(FATAL, "SIDelExpiredDataEntries: Invalid segment state");
    	    }
    	}
    }
}



/************************************************************************/
/* SISegInit(segP)  - initializes the segment	    	    	    	*/
/************************************************************************/
void
SISegInit(segP)
    SISeg *segP;
{
    SISegOffsets    *oP;
    SISegOffsets    *SIComputeSize();
    int	    	    segSize, i;
    SISegEntry      *eP;
    
    oP = SIComputeSize(&segSize);
    /* set sempahore ids in the segment */
    /* XXX */
    SISetStartEntrySection(segP, oP->offsetToFirstEntry);
    SISetEndEntrySection(segP, oP->offsetToEndOfSegemnt);
    SISetStartFreeSpace(segP, 0);
    SISetStartEntryChain(segP, InvalidOffset);
    SISetEndEntryChain(segP, InvalidOffset);
    (void) SISetNumEntries(segP, 0);
    (void) SISetMaxNumEntries(segP, MAXNUMMESSAGES);
    for (i = 0; i < MaxBackendId; i++) {
    	segP->procState[i].limit = -1; 	    /* no backend active  !!*/
    	segP->procState[i].resetState = false;
		segP->procState[i].tag = InvalidBackendTag;
    }
    /* construct a chain of free entries    	    	    	    */
    for (i = 1; i < MAXNUMMESSAGES; i++)  {
    	eP = (SISegEntry  *) ((Pointer) segP +
    	                     SIGetStartEntrySection(segP) +
    	                     (i - 1) * sizeof(SISegEntry));
    	eP->isfree = true;
    	eP->next = i * sizeof(SISegEntry); /* relative to B */
    }
    /* handle the last free entry separate  	    	    	    */
    eP = (SISegEntry  *) ((Pointer) segP +
    	                     SIGetStartEntrySection(segP) +
    	                     (MAXNUMMESSAGES - 1) * sizeof(SISegEntry));
    eP->isfree = true;
    eP->next = InvalidOffset;  /* it's the end of the chain !! */
    /*
     * Be tidy
     */
    pfree(oP);
    	                     
}
   


/************************************************************************/
/* SISegmentKill(key)   - kill any segment                              */
/************************************************************************/
void
SISegmentKill(key)
    int key;                    /* the corresponding key for the segment    */
{   
    IpcMemoryKill(key);
}	


/************************************************************************/
/* SISegmentGet(key, size)  - get a shared segment of size <size>       */
/*                returns a segment id                                  */
/************************************************************************/
IpcMemoryId
SISegmentGet(key, size, create)
    int     key;                /* the corresponding key for the segment    */
    int     size;               /* size of segment in bytes                 */
    bool    create;
{
    IpcMemoryId   shmid;

    if (create) {
	shmid = IpcMemoryCreate(key, size, IPCProtection);
    } else {
	shmid = IpcMemoryIdGet(key, size);
    }
    return(shmid);
}

/************************************************************************/
/* SISegmentAttach(shmid)   - attach a shared segment with id shmid     */
/************************************************************************/
void
SISegmentAttach(shmid)
    IpcMemoryId   shmid;
{
    shmInvalBuffer = (struct SISeg *) IpcMemoryAttach(shmid);
    if (shmInvalBuffer == IpcMemAttachFailed) {   
	/* XXX use validity function */
	elog(NOTICE, "SISegmentAttach: Could not attach segment");
	elog(FATAL, "SISegmentAttach: %m");
    }
}


/************************************************************************/
/* SISegmentInit(killExistingSegment, key)  initialize segment	    	*/
/************************************************************************/
int
SISegmentInit(killExistingSegment, key)
    bool    killExistingSegment;
    IPCKey  key;
{ 
    SISegOffsets	*oP;
    int     	    	status, segSize;
    IpcMemoryId	    	shmId;
    bool    	    	create;
    
    if (killExistingSegment) {
        /* Kill existing segment */
        /* set semaphore */
    	SISegmentKill(key);
    	
        /* Get a shared segment */
         
        oP = SIComputeSize(&segSize);
	/*
	 * Be tidy
	 */
	pfree(oP);

        create = true;
        shmId = SISegmentGet(key,segSize, create);
        if (shmId < 0) {
            perror("SISegmentGet: failed");
            return(-1);                                     /* an error */
        }

        /* Attach the shared cache invalidation  segment */
        /* sets the global variable shmInvalBuffer */
        SISegmentAttach(shmId);

        /* Init shared memory table */
        SISegInit(shmInvalBuffer);  
    } else {
    	/* use an existing segment */
    	create = false;
    	shmId = SISegmentGet(key, 0, create);
    	if (shmId < 0) {
    	    perror("SISegmentGet: getting an existent segment failed");
    	    return(-1);	    	    	    	    	    /* an error */
    	}
    	/* Attach the shared cache invalidation segment */
      	SISegmentAttach(shmId);
    }
    return(1);
}


/* synchronization of the shared buffer access	    	    */

void
SISyncInit(key)
    IPCKey	key;
{
#ifdef HAS_TEST_AND_SET
    SharedInvalidationLockId = (int)SINVALLOCKID;  /* a fixed lock */
#else /* HAS_TEST_AND_SET */
    int status;
    SharedInvalidationSemaphore =
    	IpcSemaphoreCreate(key, 1, IPCProtection, SI_LockStartValue,
    	                   &status);
    if(0) { /* XXX use validity function and check status */
    	elog(FATAL, "SISynchInit: %m");
    }
#endif /* HAS_TEST_AND_SET */
}

void
SISyncKill(key)
    IPCKey	key;
{
#ifndef HAS_TEST_AND_SET
    IpcSemaphoreKill(key);
#endif
}


void
SIReadLock()
{
#ifdef HAS_TEST_AND_SET
    SharedLock(SharedInvalidationLockId);
#else /* HAS_TEST_AND_SET */
    IpcSemaphoreLock ( SharedInvalidationSemaphore ,
		       0 , 
		       SI_SharedLock );
#endif /* HAS_TEST_AND_SET */
}


void
SIWriteLock()
{
#ifdef HAS_TEST_AND_SET
    ExclusiveLock(SharedInvalidationLockId);
#else /* HAS_TEST_AND_SET */
    IpcSemaphoreLock ( SharedInvalidationSemaphore,
		       0 ,
		      SI_ExclusiveLock );
#endif /* HAS_TEST_AND_SET */
}


void
SIReadUnlock()
{
#ifdef HAS_TEST_AND_SET
    SharedUnlock(SharedInvalidationLockId);
#else /* HAS_TEST_AND_SET */
    IpcSemaphoreLock ( SharedInvalidationSemaphore,
		       0,
		       (- SI_SharedLock) );
#endif /* HAS_TEST_AND_SET */
}


void
SIWriteUnlock()
{
#ifdef HAS_TEST_AND_SET
    ExclusiveUnlock(SharedInvalidationLockId);
#else /* HAS_TEST_AND_SET */
    IpcSemaphoreLock ( SharedInvalidationSemaphore,
		       0,
		       ( - SI_ExclusiveLock ) );
#endif /* HAS_TEST_AND_SET */
}



#ifdef _FOO_BAR_BAZ_
/************************************************************************
* debug routines
*
* This code tries to use the old lmgr setup and should not be called 
* unless you are willing to set up a spin lock for it as was done above
* to handle shared invaladation processing.
*************************************************************************/
void
SIBufferImage()
{
    int i, status;
    SISegEntry 	*SIGetFirstDataEntry();
    SISegEntry 	*eP;
    SISeg   	*segP;
    
    /* READ LOCK buffer */
    status = LMLock(SILockTableId, LockWait, &SIRelId, &SIDummyOid, &SIDummyOid,
    	    	    SIXid, MultiLevelLockRequest_ReadRelation);
    if (status == L_ERROR) {
    	    elog(FATAL, "InvalidateSharedInvalid: Could not lock buffer segment");
    }
    
    segP = shmInvalBuffer;
    fprintf(stderr, "\nDEBUG: current segment IMAGE");
    fprintf(stderr, "\n startEntrySection: %d", SIGetStartEntrySection(segP));
    fprintf(stderr, "\n endEntrySection: %d", SIGetEndEntrySection(segP));
    fprintf(stderr, "\n startFreeSpace: %d", SIGetStartFreeSpace(segP));
    fprintf(stderr, "\n startEntryChain: %d", SIGetStartEntryChain(segP));
    fprintf(stderr, "\n endEntryChain: %d", SIGetEndEntryChain(segP));
    fprintf(stderr, "\n numEntries: %d", SIGetNumEntries(segP));
    fprintf(stderr, "\n maxNumEntries: %d", SIGetMaxNumEntries(segP));
    for (i = 0; i < MaxBackendId; i++) {
    	fprintf(stderr, "\n   Backend[%2d] - limit: %3d  reset: %s", 
    	    	    i + 1,
    	    	    SIGetProcStateLimit(segP, i),
    	    	    SIGetProcStateResetState(segP, i) ? "true" : "false");
    }
    fprintf(stderr, "\n Message entries:");
    eP = SIGetFirstDataEntry(segP);
    while (eP != NULL) {
    	fprintf(stderr, "\n  cacheId: %-7d", eP->entryData.cacheId);
    	fprintf(stderr, "   free: %s", eP->isfree ? "true" : "false");
    	fprintf(stderr, "   my offset: %-4d", SIEntryOffset(segP, eP));
    	fprintf(stderr, "   next: %-4d", eP->next);
    	eP = SIGetNextDataEntry(segP, eP->next);
    }
    fprintf(stderr, "\n No further entries");
    
    fprintf(stderr, "\n No. of free entries: %d", 
    	    	    (SIGetMaxNumEntries(segP) - SIGetNumEntries(segP)));
/*  fprintf(stderr, "\n Free space chain:");
    eP = SIGetNextDataEntry(segP, SIGetStartFreeSpace(segP));
    while (eP != NULL) {
    	fprintf(stderr, "\n  free: %s", eP->isfree ? "true" : "false");
    	fprintf(stderr, "   my offset: %-4d", SIEntryOffset(segP, eP));
    	fprintf(stderr, "   next: %-4d", eP->next);
    	eP = SIGetNextDataEntry(segP, eP->next);
    }
    fprintf(stderr, "\n No further entries");
*/  
    fprintf(stderr, "\n");
    
    /* UNLOCK buffer */
    status = LMLockReleaseAll(SILockTableId, SIXid);
    if (status == L_ERROR) {
    	    elog(FATAL, "InvalidateSharedInvalid: Could not unlock buffer segment");
    }
}
#endif _FOO_BAR_BAZ_

/****************************************************************************/
/*  Invalidation functions for testing cache invalidation   	    	    */
/****************************************************************************/
void
SIinvalFunc(data)
    int data;
{   
    printf(" Backend: %d -- invalidating data (cacheId) %d\n",
    	    MyBackendId, data);
}

void
SIresetFunc()
{   
    printf("\n Backend: %d -- state reset done",
    	    MyBackendId);
}
@


1.25
log
@ifdef out some old junk that should probably be deleted
@
text
@d13 1
a13 1
 *	$Header: /private/mer/pg.latest/src/storage/ipc/RCS/sinvaladt.c,v 1.24 1992/03/11 02:17:16 mer Exp mer $
d126 1
a126 1
void
d136 2
d146 1
d198 2
a199 1
	    elog(NOTICE, "SIAssignBackendId: discarding tag %d",
d201 1
@


1.24
log
@plug memory leaks, and change functions to accept pointers to structs
@
text
@d13 1
a13 1
 *	$Header: /u/mer/pg/src/storage/ipc/RCS/sinvaladt.c,v 1.23 1991/11/21 15:45:36 mer Exp mer $
d50 5
d68 8
a75 2
TransactionIdData SIXidData;	    
TransactionId	SIXid = &SIXidData; 
@


1.23
log
@fix warn message on sun3
@
text
@d13 1
a13 1
 *	$Header: RCS/sinvaladt.c,v 1.22 91/11/14 19:39:41 kemnitz Exp Locker: mer $
d247 1
a247 1
    oP = new(SISegOffsets);
d599 1
a599 1
    SharedInvalidData  data;
d618 1
a618 1
    eP->entryData = data;
d826 4
d890 1
d902 6
a907 1
        (void) SIComputeSize(&segSize);
@


1.22
log
@protos checkin.
@
text
@d13 1
a13 1
 *	$Header: RCS/sinvaladt.c,v 1.21 91/09/05 23:28:36 hong Exp Locker: kemnitz $
d933 1
a933 1
    SharedInvalidationLockId = SINVALLOCKID;  /* a fixed lock */
@


1.21
log
@fix sequent compilation errors
@
text
@d13 1
a13 1
 *	$Header: RCS/sinvaladt.c,v 1.20 91/08/29 23:54:07 mer Exp $
d77 2
a78 2
	SISeg 		*segInOutP;
	BackendTag	tag;
d90 2
a91 2
	int		status;	/* XXX */
	SISeg		*segInOutP;
@


1.20
log
@purge old lmgr code
@
text
@d13 1
a13 1
 *	$Header: /users/mer/postgres/src/storage/ipc/RCS/sinvaladt.c,v 1.19 1991/08/14 22:10:42 mer Exp mer $
d53 1
a53 1
LockId SharedInvalidationLockId;
@


1.19
log
@get rid of obsolete junk with creating a phony xactID and phony table
@
text
@d13 1
a13 1
 *	$Header: RCS/sinvaladt.c,v 1.18 91/07/22 14:20:32 mer Exp Locker: mer $
a25 3
#include "storage/pladt.h"
#include "storage/pldebug.h"
#include "storage/plm.h"
d27 1
a49 2
 *	SILockTableId
 * 		lock table holding buffer locks
a64 1
LockTableId 	SILockTableId;
a120 1
    LockTableId	    	    LMLockTableCreate();
d872 1
a872 1
	Note("SISegmentAttach: Could not attach segment",DEBERR);
d1008 1
a1008 1
#ifdef DEBUG
d1011 4
d1077 1
a1077 1
#endif DEBUG
@


1.18
log
@new lock manager function call.
@
text
@d13 1
a13 1
 *	$Header: storage/ipc/RCS/sinvaladt.c,v 1.17 91/06/10 20:57:51 kemnitz Exp Locker: mer $
a129 11
    SIRelId = LtCreateRelId(SIDbId,0);
    
    /*
     * Allocate a transaction id to allow use of the lock table.
     * Is there a non-hack which can be used to allow lock table access?
     * Maybe, use the getpid() or MyBackendId with a special lock table?
     */
    GetNewTransactionId(SIXid);
    
    SILockTableId = InitMultiLevelLockm();

d1014 1
d1079 1
a1079 1
   
@


1.17
log
@generalization of spinlocks.
@
text
@d13 1
a13 1
 *	$Header: ipc/RCS/sinvaladt.c,v 1.16 91/04/01 08:47:28 hong Exp Locker: kemnitz $
d139 1
a139 3
    SILockTableId = LMLockTableCreate("multiLevel",
				      MultiLevelLockTable,
				      LockTableNormal);
@


1.16
log
@for debugging memory leaks
@
text
@d13 1
a13 1
 *	$Header: RCS/sinvaladt.c,v 1.15 90/11/12 08:16:01 hong Exp $
d56 1
a56 1
#ifdef sequent
d951 1
a951 1
#ifdef sequent
d953 1
a953 1
#else /* sequent */
d961 1
a961 1
#endif /* sequent */
d968 1
a968 1
#ifndef sequent
d977 1
a977 1
#ifdef sequent
d979 1
a979 1
#else /* sequent */
d983 1
a983 1
#endif /* sequent */
d990 1
a990 1
#ifdef sequent
d992 1
a992 1
#else /* sequent */
d996 1
a996 1
#endif /* sequent */
d1003 1
a1003 1
#ifdef sequent
d1005 1
a1005 1
#else /* sequent */
d1009 1
a1009 1
#endif /* sequent */
d1016 1
a1016 1
#ifdef sequent
d1018 1
a1018 1
#else /* sequent */
d1022 1
a1022 1
#endif /* sequent */
@


1.15
log
@clean up
@
text
@d13 1
a13 1
 *	$Header: RCS/sinvaladt.c,v 1.14 90/10/16 23:33:27 hong Exp Locker: hong $
d638 1
a638 1
    eP->free = false;
d700 1
a700 1
    e1P->free = true;
d836 1
a836 1
    	eP->free = true;
d843 1
a843 1
    eP->free = true;
d1064 1
a1064 1
    	fprintf(stderr, "   free: %s", eP->free ? "true" : "false");
d1076 1
a1076 1
    	fprintf(stderr, "\n  free: %s", eP->free ? "true" : "false");
@


1.14
log
@replace semaphores with hardware locks for sequent
@
text
@d13 1
a13 1
 *	$Header: RCS/sinvaladt.c,v 1.13 90/09/30 14:41:26 goh Exp Locker: hong $
d952 1
a952 1
    SharedInvalidationLockId = 2;  /* a fixed lock */
@


1.13
log
@cleaned up some code, no more system dependent stuff ( hopefully )
@
text
@d13 1
a13 1
 *	$Header: RCS/sinvaladt.c,v 1.12 90/09/30 14:17:53 goh Exp Locker: goh $
d56 3
d60 1
d951 3
d961 1
d968 1
d970 1
d977 3
d983 1
d990 3
d996 1
d1003 3
d1009 1
d1016 3
d1022 1
@


1.12
log
@removed apparent dependencies on <sys/{shm,sem}.h>, but still
testing
@
text
@d13 1
a13 1
 *	$Header: RCS/sinvaladt.c,v 1.11 90/09/30 13:58:49 goh Exp Locker: goh $
a24 16

/*******************************************

 XXX These should *not* be used directly; fix the interface in ipc*.h. 
 XXX Taken out, but still testing

#ifndef sequent
#include <sys/shm.h>
#include <sys/sem.h>
#else
#include "/usr/att/usr/include/sys/shm.h"
#include "/usr/att/usr/include/sys/sem.h"
#endif

*********************************************/

a966 1
    
a969 18
		       
    /**************
    int	    status;
    struct sembuf   sops;

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

      XXX - remove next time round

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

    ***************/
a975 1

a978 19
    
    /*************

      XXX - remove next time round

    int	    status;
    struct sembuf   sops;

    sops.sem_op = SI_ExclusiveLock;
    sops.sem_flg = 0;
    sops.sem_num = 0;
    
    status = semop(SharedInvalidationSemaphore, (struct sembuf **)&sops, 1);
    if (status == -1) {
    	perror("semop");
    	exitpg(255);
    }

    ************/
a984 1

a987 18
    /*************

      XXX - remove next time around

    int	    status;
    struct sembuf   sops;

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

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

    ***************/
a993 1

a996 14
    /**********
    int	    status;
    struct sembuf   sops;

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

    status = semop(SharedInvalidationSemaphore, (struct sembuf **)&sops, 1);
    if (status == -1) {
    	perror("semop");
    	exitpg(255);
    }
    ************/
@


1.11
log
@got rid of unneeded semctl() calls.  Part of clean up
to isolate Sys V (read ipc) dependencies
@
text
@d13 1
a13 1
 *	$Header: RCS/sinvaladt.c,v 1.10 90/08/14 15:41:59 cimarron Exp $
d26 5
a30 1
/* XXX These should *not* be used directly; fix the interface in ipc*.h. */
d39 2
a918 1
    struct  shmid_ds    shbuf;
a935 22
	/*************************************
	  
	  XXX - the following 10 lines just copy buffer info 
	  into shbuf, and then copy it back.
	  shbuf is then never used again, so these
	  lines are theoretically unecessary.
	  If things don't break, we should probably
	  permanently remove them

        status = shmctl(shmId, IPC_STAT, &shbuf);       
        if (status < 0) {
            perror("shmctl:stat");
            return(-1);
        }
        status = shmctl(shmId, IPC_SET, &shbuf);        
        if (status < 0) {
            perror("shmctl:set");
            return(-1);
        }
	
	***************************************/

d983 6
d996 2
d1003 2
d1011 9
d1032 2
d1040 8
d1060 2
d1068 5
d1085 1
@


1.10
log
@Updating from revision 1.9 to revision 1.10
@
text
@d930 11
a940 2
     
        status = shmctl(shmId, IPC_STAT, &shbuf);       /* XXX unneeded? */
d945 1
a945 1
        status = shmctl(shmId, IPC_SET, &shbuf);        /* XXX unneeded? */
d950 3
@


1.9
log
@Added sequent compatibility stuff.
@
text
@d13 1
a13 1
 *	$Header: RCS/sinvaladt.c,v 1.8 90/03/31 19:12:45 cimarron Exp Locker: kemnitz $
d24 1
a24 1
#include "ipci.h"
d35 6
a40 7
#include "ipc.h"
#include "log.h"
#include "pladt.h"
#include "pldebug.h"
#include "plm.h"

#include "sinvaladt.h"
@


1.8
log
@added comments.
@
text
@d13 1
a13 1
 *	$Header$
d27 1
d30 4
@


1.7
log
@Replaced on_exit() with on_exitpg()
@
text
@d1 6
a6 3
/*
 * sinvaladt.c --
 *  POSTGRES shared cache invalidation segment definitions.
d8 7
a14 2
 * Identification:
 * $Header: RCS/sinvaladt.c,v 1.6 90/02/12 19:48:18 cimarron Exp Locker: kemnitz $
a15 1
 
d17 7
a23 1
/* XXX yucky order dependency */
d25 1
d38 24
d63 2
a64 2
SISeg		*shmInvalBuffer;	/* the shared buffer segment, set by */
    	    	    	    	    	/*   SISegmentAttach()	    	    */
d66 6
a71 2
extern BackendId    MyBackendId;/* might be removed later, used only for    */
    	    	    	    	/* debugging in debug routines (end of file)*/
d73 4
a76 5
static	OID 	SIDbId = 0; 	/* identification of the buffer (disappears)*/
    	LRelId  SIRelId;    	/* identification of the buffer */
    	OID 	SIDummyOid = InvalidObjectId;
    	TransactionId	SIXid;	    	/* identification of the buffer */
    	LockTableId 	SILockTableId;  /* lock table holding buffer locks */
d108 2
a109 2
	SISeg 		*segInOutP;
	BackendId 	backendId;
d111 1
a111 1
	/* mark all messages as read */
d113 4
a116 3
/*    Assert(segP->procState[backendId - 1].tag == MyBackendTag); */
	segInOutP->procState[backendId - 1].resetState = false;
	segInOutP->procState[backendId - 1].limit = SIGetNumEntries(segInOutP);
d118 1
d124 3
a126 2
	SISeg 		*segInOutP;
{   LRelId  	    	    LtCreateRelId();
d130 1
a130 1
	Assert(MyBackendTag > 0);
d133 11
a143 8
	/*
	 * Allocate a transaction id to allow use of the lock table.
	 * Is there a non-hack which can be used to allow lock table access?
	 * Maybe, use the getpid() or MyBackendId with a special lock table?
	 */
    SIXid = LMITransactionIdCopy(GetNewTransactionId());
    SILockTableId = LMLockTableCreate("multiLevel", MultiLevelLockTable,
    	    	    	    	    	LockTableNormal);
d145 1
a145 1
	MyBackendId = SIAssignBackendId(segInOutP, MyBackendTag);
d148 3
a150 3
	elog(DEBUG, "SIBackendInit: backend tag %d; backend id %d.",
		MyBackendTag, MyBackendId);
#endif	/* defined(INVALIDDEBUG) */
d152 2
a153 2
	SISetActiveProcess(segInOutP, MyBackendId);
	on_exitpg(CleanupInvalidationState, segInOutP);
d156 4
d162 2
a163 2
	SISeg		*segInOutP;
	BackendTag	backendTag;
d165 2
a166 2
	Index		index;
	ProcState	*stateP;
d168 1
a168 1
	stateP = NULL;
d170 7
a176 3
	for (index = 0; index < MaxBackendId; index += 1) {
		if (segInOutP->procState[index].tag == InvalidBackendTag ||
				segInOutP->procState[index].tag == backendTag) {
d178 12
a189 3
			stateP = &segInOutP->procState[index];
			break;
		}
d191 1
a191 8
		if (!PointerIsValid(stateP) ||
				(segInOutP->procState[index].resetState &&
					(!stateP->resetState ||
						stateP->tag < backendTag)) ||
				(!stateP->resetState &&
					(segInOutP->procState[index].limit <
						stateP->limit ||
						stateP->tag < backendTag))) {
d193 4
a196 2
			stateP = &segInOutP->procState[index];
		}
d198 1
d200 7
a206 6
	/* verify that all "procState" entries checked for matching tags */
	for (index += 1; index < MaxBackendId; index += 1) {
		if (segInOutP->procState[index].tag == backendTag) {
			elog (FATAL, "SIAssignBackendId: tag %d found twice",
				backendTag);
		}
d208 1
d210 1
a210 3
	if (stateP->tag != InvalidBackendTag) {
		if (stateP->tag == backendTag) {
			elog(NOTICE, "SIAssignBackendId: reusing tag %d",
d212 2
a213 6
				backendTag);
		} else {
			elog(NOTICE, "SIAssignBackendId: discarding tag %d",
				stateP->tag);
		}
	}
a214 1
	stateP->tag = backendTag;
d216 3
a218 2
	return (1 + stateP - &segInOutP->procState[0]);
}
a219 4
/************************************************************************
*************************************************************************
* The following function should be called only by the postmaster !!
*/
d226 2
a227 2
SISeg 	*segP;
int 	backendId;
d229 1
a229 1
	/* XXX call me.... */
d231 3
a233 3
	segP->procState[backendId - 1].resetState = false;
	segP->procState[backendId - 1].limit = -1;
	segP->procState[backendId - 1].tag = InvalidBackendTag;
d236 4
d242 2
a243 2
	int		status;	/* XXX */
	SISeg		*segInOutP;	/* XXX style */
d245 1
a245 1
	Assert(PointerIsValid(segInOutP));
d247 1
a247 1
	SISetDeadProcess(segInOutP, MyBackendId);
d250 1
d256 4
a259 3
int *segSize;
{  int      	A, B, a, b, totalSize;
   SISegOffsets *oP;
d262 1
a262 1
    a = SizeSISeg;  /* offset to first data entry */
d275 1
d280 1
a280 1
SISeg *segP;
d284 2
d291 2
a292 2
SISeg *segP;
IpcSemaphoreId id;
d297 1
d299 1
a299 1
/* SISetStartEntrySection(segP, offset)     - sets the offset	*/
d303 2
a304 2
SISeg *segP;
Offset offset;
d308 1
d310 1
a310 1
/* SIGetStartEntrySection(segP)     - returnss the offset   	*/
d319 1
d321 1
a321 1
/* SISetEndEntrySection(segP, offset) 	- sets the offset   	*/
d325 2
a326 2
SISeg *segP;
Offset offset;
d330 1
d336 1
a336 1
SISeg *segP;
d340 1
d346 2
a347 2
SISeg *segP;
Offset offset;
d351 1
d357 1
a357 1
SISeg *segP;
a361 2


d367 2
a368 2
SISeg *segP;
Offset offset;
d372 1
d378 1
a378 1
SISeg *segP;
d382 1
d388 2
a389 2
SISeg *segP;
int   num;
d398 1
d404 1
a404 1
SISeg *segP;
d406 1
a406 1
        return(segP->numEntries);
d409 1
d415 2
a416 2
SISeg *segP;
int   num;
d426 1
d432 1
a432 1
SISeg *segP;
d436 1
d442 2
a443 2
SISeg 	*segP;
int 	i;
d447 1
d453 2
a454 2
SISeg 	*segP;
int 	i;
d458 1
d464 2
a465 2
SISeg *segP;
int   num;
d474 1
d480 2
a481 2
SISeg *segP;
int   num;
d490 1
d496 4
a499 3
SISeg *segP;
Offset offset;
{   segP->startFreeSpace = offset;
d501 1
d507 3
a509 2
SISeg *segP;
{   return(segP->startFreeSpace);
d513 1
d519 3
a521 2
SISeg *segP;
{   SISegEntry  *eP;
d531 1
a531 1
                           startChain    );
d535 1
d541 3
a543 2
SISeg *segP;
{   SISegEntry  *eP;
d553 1
a553 1
                           endChain    );
d556 1
d562 4
a565 3
SISeg 	    *segP;
Offset       offset;
{   SISegEntry  *eP;
d576 1
d582 2
a583 2
SISeg 	*segP;
int 	n;      /* must range from 1 to MaxMessages */
d595 1
d604 2
a605 2
SISeg  	*segP;
SISegEntry *entryP;
a612 1
                       
d619 4
a622 3
SISeg *segP;
SharedInvalidData  data;
{   Offset  	    offsetToNewData;
d655 2
d662 4
a665 3
SISeg 	*segP;
int 	num;
{   int i;
d677 2
a678 1
} 
d685 1
a685 1
SISeg 	*segP;
d708 1
d717 1
a717 1
SISeg 	*segP;
d719 1
a719 1
	int i;
d729 1
d737 6
a742 5
SISeg 	*segP;
int 	backendId;
void    (*invalFunction)();
void    (*resetFunction)();
{   int i;
d776 1
d782 1
a782 1
SISeg 	*segP;
d805 1
d811 3
a813 2
SISeg *segP;
{   SISegOffsets    *oP;
d848 2
a849 1
}   
d857 1
a857 1
int key;                    /* the corresponding key for the segment    */
d859 2
a860 2
        IpcMemoryKill(key);
}  /* end SISegmentKill */
d869 3
a871 3
int     key;                /* the corresponding key for the segment    */
int     size;               /* size of segment in bytes                 */
bool    create;
d873 1
a873 1
        IpcMemoryId   shmid;
d875 7
a881 7
        if (create) {
                shmid = IpcMemoryCreate(key, size, IPCProtection);
        } else {
                shmid = IpcMemoryIdGet(key, size);
        }
        return(shmid);
}  /* end SISegmentGet */
a882 1

d888 1
a888 1
IpcMemoryId   shmid;
d890 6
a895 6
        shmInvalBuffer = (struct SISeg *) IpcMemoryAttach(shmid);
        if (shmInvalBuffer == IpcMemAttachFailed) {   
            /* XXX use validity function */
                Note("SISegmentAttach: Could not attach segment",DEBERR);
                elog(FATAL, "SISegmentAttach: %m");
        }
d904 2
a905 2
        bool    killExistingSegment;
        IPCKey  key;
d957 1
d962 1
a962 1
IPCKey	key;
d972 1
d975 1
a975 1
IPCKey	key;
d998 1
d1016 1
d1034 1
a1053 2


a1054 1
*************************************************************************
d1056 1
a1056 1
*/
d1117 2
a1118 1
}   
d1125 1
a1125 1
int data;
d1130 1
@


1.6
log
@added buffer manager statistics and exitpg() stuff -cim
@
text
@d6 1
a6 1
 * $Header: RCS/sinvaladt.c,v 1.5 90/02/01 17:39:27 goh Exp $
d51 1
a51 1
 *	of exit (via on_exit).
d106 1
a106 1
	on_exit(CleanupInvalidationState, segInOutP);
@


1.5
log
@no dillon wierd locks
@
text
@d6 1
a6 1
 * $Header: RCS/sinvaladt.c,v 1.2 89/02/02 16:16:05 dillon Stab $
d913 1
a913 1
    	exit(255);
d930 1
a930 1
    	exit(255);
d947 1
a947 1
    	exit(255);
@


1.4
log
@Working version of C-only demo
@
text
@d6 1
a6 1
 * $Header: /usr6/postgres/mao/postgres/src/storage/ipc/RCS/sinvaladt.c,v 1.3 89/08/03 00:06:24 dillon Exp $
d24 1
a24 1
/*REMOVED IpcSemaphoreId	SharedInvalidationSemaphore;*/
a862 1
/* PROCEDURE REMOVED
d871 1
a871 1
    if(0) { /* XXX use validity function and check status 
a874 2
*/

d886 2
a887 1
    TASReadLock(TASLOCK_BUFINVAL);
a888 3
	/* REMOVED
    
    TASLOCK_BUFINVAL
a897 1
	*/
d903 2
a905 3
    TASWriteLock(TASLOCK_BUFINVAL);

	/* REMOVED
a914 1
	*/
a919 3
    TASReadUnLock(TASLOCK_BUFINVAL);

    /* REMOVED 
a931 1
    */
a936 3
    TASWriteUnLock(TASLOCK_BUFINVAL);

    /* REMOVED
a948 1
    */
@


1.3
log
@shared memory lock manager code (does not used semaphores)
@
text
@d6 1
a6 1
 * $Header: sinvaladt.c,v 1.2 89/02/02 16:16:05 dillon Locked $
@


1.2
log
@Txfer from old tree
@
text
@d6 1
a6 1
 * $Header: sinvaladt.c,v 1.5 88/08/30 20:36:47 dillon Locked $
d24 1
a24 1
IpcSemaphoreId	SharedInvalidationSemaphore;
d863 1
d872 1
a872 1
    if(0) { /* XXX use validity function and check status */
d876 2
d889 1
a889 2
    int	    status;
    struct sembuf   sops;
d891 3
d903 1
a908 2
    int	    status;
    struct sembuf   sops;
d910 3
d922 1
d928 3
d943 1
d949 3
d964 1
@


1.1
log
@Initial revision
@
text
@a0 1

a1 26
 * 
 * POSTGRES Data Base Management System
 * 
 * Copyright (c) 1988 Regents of the University of California
 * 
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for educational, research, and non-profit purposes and
 * without fee is hereby granted, provided that the above copyright
 * notice appear in all copies and that both that copyright notice and
 * this permission notice appear in supporting documentation, and that
 * the name of the University of California not be used in advertising
 * or publicity pertaining to distribution of the software without
 * specific, written prior permission.  Permission to incorporate this
 * software into commercial products can be obtained from the Campus
 * Software Office, 295 Evans Hall, University of California, Berkeley,
 * Ca., 94720 provided only that the the requestor give the University
 * of California a free licence to any derived software for educational
 * and research purposes.  The University of California makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 * 
 */



/*
d6 1
a6 1
 * $Header: sinvaladt.c,v 1.1 88/11/11 16:37:39 postgres Exp $
@
