head	1.11;
access;
symbols
	release_4_2:1.11
	aix_ok:1.10
	Version_2_1:1.7
	Version_2:1.5
	C_Demo_1:1.3;
locks; strict;
comment	@ * @;


1.11
date	94.06.16.03.23.06;	author aoki;	state Exp;
branches;
next	1.10;

1.10
date	93.09.22.00.43.00;	author aoki;	state Exp;
branches;
next	1.9;

1.9
date	93.07.27.00.53.55;	author aoki;	state Exp;
branches;
next	1.8;

1.8
date	92.03.05.00.36.25;	author hong;	state Exp;
branches;
next	1.7;

1.7
date	90.08.18.00.38.57;	author cimarron;	state Exp;
branches;
next	1.6;

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

1.5
date	90.06.08.15.37.56;	author cimarron;	state Version_2;
branches;
next	1.4;

1.4
date	89.10.01.15.51.34;	author hirohama;	state Exp;
branches;
next	1.3;

1.3
date	89.09.05.16.56.53;	author mao;	state C_Demo_1;
branches;
next	1.2;

1.2
date	89.02.02.18.01.10;	author aoki;	state Stab;
branches;
next	1.1;

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


desc
@@


1.11
log
@include port-protos.h for port routines (random/srandom)
@
text
@/* ----------------------------------------------------------------
 *   FILE
 *	hrnd.c
 *
 *   DESCRIPTION
 *	POSTGRES heap access method randomization code.
 *
 *   NOTES
 *
 *   IDENTIFICATION
 *	$Header: /import/faerie/faerie/aoki/postgres/src/backend/access/heap/RCS/hrnd.c,v 1.10 1993/09/22 00:43:00 aoki Exp aoki $
 * ----------------------------------------------------------------
 */

#include "tmp/c.h"

RcsId("$Header: /import/faerie/faerie/aoki/postgres/src/backend/access/heap/RCS/hrnd.c,v 1.10 1993/09/22 00:43:00 aoki Exp aoki $");

#include "storage/block.h"
#include "storage/buf.h"
#include "storage/bufmgr.h"
#include "storage/bufpage.h"

#include "utils/memutils.h"
#include "utils/rel.h"

#ifdef	RANDOMDEBUG
#include "utils/log.h"
#endif	/* defined(RANDOMDEBUG) */

#include "access/hrnd.h"

#include "fmgr.h"		/* for port-protos */
#include "port-protos.h"	/* for random/srandom */

static bool		DisableHeapRandomization = false;
static BlockNumber	RandomBlockIndexList[1 + MaxLengthOfBlockIndexList];
static bool		ClusterIsEnabled;
static BlockNumber	ClusterBlockIndex;

/*
 * BlockIndexRandomlyFillRandomBlockIndexList --
 *	Fills RandomBlockIndexList with random indexes given number of blocks.
 */
extern
void
BlockIndexRandomlyFillRandomBlockIndexList ARGS((
	BlockNumber	numberOfBlocks
));

/*
 * BlockIndexFillRandomBlockIndexList --
 *	Fills RandomBlockIndexList with indexes given number of blocks and id.
 */
extern
void
BlockIndexFillRandomBlockIndexList ARGS((
	BlockNumber	numberOfBlocks,
	ObjectId	id
));

/*
 * ObjectIdHashBlockIndex --
 *	Returns a block index hashed from an object id.
 */
extern
BlockNumber
ObjectIdHashBlockIndex ARGS((
	ObjectId	id,
	Index		method
));

void
InitRandom()
{
	if (PointerIsValid(getenv("POSTGROWS"))) {
		DisableHeapRandomization = true;
		RandomBlockIndexList[0] = InvalidBlockNumber;
	} else {
		DisableHeapRandomization = false;
		RandomBlockIndexList[MaxLengthOfBlockIndexList] =
			InvalidBlockNumber;
	}
	ClusterBlockIndex = InvalidBlockNumber;
}

void
setclusteredappend(on)
	bool	on;
{
	ClusterBlockIndex = InvalidBlockNumber;
	ClusterIsEnabled = on;
}

BlockNumber
getclusterblockindex()
{
	if (!ClusterIsEnabled) {
		Assert(!BlockNumberIsValid(ClusterBlockIndex));
	}
	return (ClusterBlockIndex);
}

void
setclusterblockindex(blockIndex)
	BlockNumber	blockIndex;
{
	Assert(BlockNumberIsValid(blockIndex));

	if (ClusterIsEnabled) {
		ClusterBlockIndex = blockIndex;

#ifdef	RANDOMDEBUG
		elog(DEBUG, "setclusterblockindex(%d)", blockIndex);
#endif	/* defined(RANDOMDEBUG) */
	}
}

BlockIndexList
RelationGetRandomBlockIndexList(relation, id)
	Relation	relation;
	ObjectId	id;
{
	Assert(RelationIsValid(relation));

	if (!DisableHeapRandomization) {
		if (!ObjectIdIsValid(id)) {
			BlockIndexRandomlyFillRandomBlockIndexList(
				RelationGetNumberOfBlocks(relation));
		} else {
			BlockIndexFillRandomBlockIndexList(
				RelationGetNumberOfBlocks(relation), id);
		}
	}

	return (RandomBlockIndexList);
}

/*
 * XXX RelationContainsUsableBlock uses heuristics instead of statistics.
 */
bool
RelationContainsUsableBlock(relation, blockIndex, size, numberOfFailures)
	Relation	relation;
	BlockNumber	blockIndex;
	Size		size;
	Index		numberOfFailures;
{
	BlockNumber	numberOfBlocks;
	BlockSize	fillLimit;
	PageFreeSpace	pageFreeSpace;
	Buffer		buffer;

	Assert(RelationIsValid(relation));
	Assert(size < BLCKSZ);

	numberOfBlocks = RelationGetNumberOfBlocks(relation);
	Assert(numberOfBlocks > 0);

#ifndef	DOCLUSTER
	if (/* type of relation is temporary */ 1) {
		fillLimit = 0;		/* XXX -1 is better? */
	} else
#endif
	if (ClusterIsEnabled &&
			numberOfFailures == ClusteredNumberOfFailures) {

		fillLimit = ClusteredBlockFillLimit * (BLCKSZ / FillLimitBase);
	} else {
		switch (numberOfBlocks) {
		case 1:
			fillLimit = OneBlockFillLimit;
			break;
		case 2:
			fillLimit = TwoBlockFillLimit;
			break;
		case 3:
			fillLimit = ThreeBlockFillLimit;
			break;
		default:
			fillLimit = ManyBlockFillLimit;
			break;
		}
		fillLimit += FillLimitAdjustment(numberOfFailures);
		fillLimit *= BLCKSZ / FillLimitBase;
	}

	buffer = ReadBuffer(relation, blockIndex);
	pageFreeSpace = PageGetFreeSpace(BufferSimpleGetPage(buffer));
	ReleaseBuffer(buffer);

	return ((bool)((int32)pageFreeSpace - (int32)LONGALIGN(size) >
		(int32)fillLimit));
}

void
BlockIndexRandomlyFillRandomBlockIndexList(numberOfBlocks)
	BlockNumber	numberOfBlocks;
{
	Index	entry;

	if (numberOfBlocks < MaxLengthOfBlockIndexList) {
		RandomBlockIndexList[numberOfBlocks] = InvalidBlockNumber;
	}
	for (entry = 0; entry < Min(numberOfBlocks, MaxLengthOfBlockIndexList);
			entry += 1) {

		Index		index;

		do {
			BlockNumber	blockIndex;

			blockIndex = random() % numberOfBlocks;
			RandomBlockIndexList[entry] = blockIndex;
			for (index = 0; index < entry; index += 1) {
				if (RandomBlockIndexList[index] == blockIndex) {
					break;
				}
			}
		} while (index != entry);
	}
#ifdef	RANDOMDEBUG
	elog(DEBUG, "RandomlyFillRandomBlockIndexList returns [%d,%d,%d,%d]",
		RandomBlockIndexList[0],
		RandomBlockIndexList[1],
		RandomBlockIndexList[2],
		RandomBlockIndexList[3]);
#endif	/* defined(RANDOMDEBUG) */
}

void
BlockIndexFillRandomBlockIndexList(numberOfBlocks, id)
	BlockNumber	numberOfBlocks;
	ObjectId	id;
{
	Index	entry;
	Index	method = 0;

	if (numberOfBlocks < MaxLengthOfBlockIndexList) {
		RandomBlockIndexList[numberOfBlocks] = InvalidBlockNumber;
	}
	for (entry = 0; entry < Min(numberOfBlocks, MaxLengthOfBlockIndexList);
			entry += 1) {

		Index		index;

		do {
			BlockNumber	blockIndex;

			blockIndex = ObjectIdHashBlockIndex(id, method)
				% numberOfBlocks;
			method += 1;
			RandomBlockIndexList[entry] = blockIndex;
			for (index = 0; index < entry; index += 1) {
				if (RandomBlockIndexList[index] == blockIndex) {
					break;
				}
			}
		} while (index != entry);
	}
#ifdef	RANDOMDEBUG
	elog(DEBUG, "FillRandomBlockIndexList(%d,%d) returns [%d,%d,%d,%d]",
		numberOfBlocks, id,
		RandomBlockIndexList[0],
		RandomBlockIndexList[1],
		RandomBlockIndexList[2],
		RandomBlockIndexList[3]);
#endif	/* defined(RANDOMDEBUG) */
}

/* XXX tune me.  case 0 is not very random -> good? bad? */
BlockNumber
ObjectIdHashBlockIndex(id, method)
	ObjectId	id;
	Index		method;
{
	BlockNumber	index;

	switch (method % 5) {
	case 0:
		index = 17 + ((id << 2) ^ (id >> 1)) + id * (1 + (method >> 1));
		break;
	case 1:
		index = 37 + ((id << 3) ^ (id >> 2)) + id * (method >> 2);
		break;
	case 2:
		index = 67 + ((id << 5) ^ (id >> 3)) + id * (method >> 1);
		break;
	case 3:
		index = 107 + ((id << 7) ^ (id >> 5)) + id * (method >> 2);
		break;
	case 4:
		index = 137 + ((id << 11) ^ (id >> 7)) + id * (method >> 1);
		break;
	default:
		Assert(0);
		break;
	}
	return(index + method);
}
@


1.10
log
@using enum in the Assert test is non-portable
@
text
@d11 1
a11 1
 *	$Header$
d17 1
a17 1
RcsId("$Header: /home2/aoki/postgres/src/backend/access/heap/RCS/hrnd.c,v 1.9 1993/07/27 00:53:55 aoki Exp $");
d33 3
@


1.9
log
@get rid of bogus extern
@
text
@d1 5
a5 2
/*
 * hrnd.c --
d7 6
d17 1
a17 1
RcsId("$Header: /home2/aoki/postgres/src/backend/access/heap/RCS/hrnd.c,v 1.9 1993/07/21 00:57:11 aoki Exp $");
d293 1
a293 1
		Assert(false);
@


1.8
log
@cleaning up and whacking out buffer leaks
@
text
@d8 1
a8 1
RcsId("$Header: RCS/hrnd.c,v 1.7 90/08/18 00:38:57 cimarron Exp Locker: hong $");
a63 2
	extern Pointer	getenv();

@


1.7
log
@eliminated less significant .h files
@
text
@d8 1
a8 1
RcsId("$Header: RCS/hrnd.c,v 1.6 90/08/13 16:43:38 cimarron Exp Locker: cimarron $");
d178 1
a178 1
	buffer = RelationGetBuffer(relation, blockIndex, L_PIN);
d180 1
a180 1
	BufferPut(buffer, L_UNPIN);
@


1.6
log
@added pathnames to include statements
@
text
@d8 1
a8 1
RcsId("$Header: RCS/hrnd.c,v 1.5 90/06/08 15:37:56 cimarron Version_2 Locker: cimarron $");
d15 1
a15 1
#include "tmp/align.h"
@


1.5
log
@slight change to obsolete TupleSize
@
text
@d6 1
a6 1
#include "c.h"
d8 10
a17 5
#include "align.h"
#include "block.h"
#include "buf.h"
#include "bufmgr.h"
#include "bufpage.h"
d19 1
a19 1
#include "log.h"
a20 2
#include "oid.h"
#include "rel.h"
d22 1
a22 3
#include "hrnd.h"

RcsId("$Header: RCS/hrnd.c,v 1.4 89/10/01 15:51:34 hirohama Exp Locker: hirohama $");
@


1.4
log
@temporary disabling of clustering
@
text
@d21 1
a21 1
RcsId("$Header: RCS/hrnd.c,v 1.3 89/09/05 16:56:53 mao C_Demo_1 Locker: hirohama $");
d135 1
a135 1
	TupleSize	size;
@


1.3
log
@Working version of C-only demo
@
text
@d21 1
a21 1
RcsId("$Header: /usr6/postgres/mao/postgres/src/access/heap/RCS/hrnd.c,v 1.2 89/02/02 18:01:10 aoki Stab $");
d149 5
@


1.2
log
@MERGE WITH OLD TREE
@
text
@d21 1
a21 1
RcsId("$Header: hrnd.c,v 1.3 88/07/24 00:30:34 aoki Locked $");
@


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.
 * 
 */



/*
d21 1
a21 1
RcsId("$Header: hrnd.c,v 1.1 88/11/11 16:42:17 postgres Exp $");
@
