示例#1
0
文件: bitcount.c 项目: kaigai/toybox
Datum
popc_or(PG_FUNCTION_ARGS)
{
	VarBit	   *arg1 = PG_GETARG_VARBIT_P(0);
	VarBit	   *arg2 = PG_GETARG_VARBIT_P(1);
	bits8	   *ptr1 = VARBITS(arg1);
	bits8	   *ptr2 = VARBITS(arg2);
	int32		count = 0;
	int			offset = 0;
	int			bitlen;

	if (VARBITLEN(arg1) != VARBITLEN(arg2))
		ereport(ERROR,
				(errcode(ERRCODE_STRING_DATA_LENGTH_MISMATCH),
				 errmsg("cannot AND bit strings of different sizes")));
#ifdef __GNUC__
	bitlen = LONGALIGN_DOWN(VARBITBYTES(arg1));

	for (offset=0; offset < bitlen; offset += sizeof(long))
		count += __builtin_popcountl(*((long *)(ptr1 + offset)) |
									 *((long *)(ptr2 + offset)));
#endif
	bitlen = VARBITBYTES(arg1);
	while (offset < bitlen)
	{
		count += bitcount_map[ptr1[offset] & ptr2[offset]];
		offset++;
	}
	PG_RETURN_INT32(count);
}
示例#2
0
/*
 * pgfincore_file handle the mmaping, mincore process (and access file, etc.)
 */
static int
pgfincore_file(char *filename, pgfincoreStruct *pgfncr)
{
	int		flag=1;
	int		flag_dirty=1;

	int		len, bitlen;
	bits8	*r;
	bits8	x = 0;
	register int64 pageIndex;


	/*
	 * We use the AllocateFile(2) provided by PostgreSQL.  We're going to
	 * close it ourselves even if PostgreSQL close it anyway at transaction
	 * end.
	 */
	FILE	*fp;
	int	fd;
	struct stat st;

#ifndef HAVE_FINCORE
	void 		  *pa  = (char *) 0;
#endif
	unsigned char *vec = (unsigned char *) 0;

	/*
	 * OS Page size
	 */
	pgfncr->pageSize  = sysconf(_SC_PAGESIZE);

	/*
	 * Initialize counters
	 */
	pgfncr->pages_mem		= 0;
	pgfncr->group_mem		= 0;
	pgfncr->pages_dirty		= 0;
	pgfncr->group_dirty		= 0;
	pgfncr->rel_os_pages	= 0;

	/*
	 * Fopen and fstat file
	 * fd will be provided to posix_fadvise
	 * if there is no file, just return 1, it is expected to leave the SRF
	 */
	fp = AllocateFile(filename, "rb");
	if (fp == NULL)
                return 1;

	fd = fileno(fp);

	if (fstat(fd, &st) == -1)
	{
		FreeFile(fp);
		elog(ERROR, "Can not stat object file : %s",
		     filename);
		return 2;
	}

	/*
	* if file ok
	* then process
	*/
	if (st.st_size != 0)
	{
		/* number of pages in the current file */
		pgfncr->rel_os_pages = (st.st_size+pgfncr->pageSize-1)/pgfncr->pageSize;

#ifndef HAVE_FINCORE
		pa = mmap(NULL, st.st_size, PROT_NONE, MAP_SHARED, fd, 0);
		if (pa == MAP_FAILED)
		{
			FreeFile(fp);
			elog(ERROR, "Can not mmap object file : %s, errno = %i,%s\nThis error can happen if there is not enought space in memory to do the projection. Please mail [email protected] with '[pgfincore] ENOMEM' as subject.",
			     filename, errno, strerror(errno));
			return 3;
		}
#endif

		/* Prepare our vector containing all blocks information */
		vec = calloc(1, (st.st_size+pgfncr->pageSize-1)/pgfncr->pageSize);
		if ((void *)0 == vec)
		{
#ifndef HAVE_FINCORE
			munmap(pa, st.st_size);
#endif
			FreeFile(fp);
			elog(ERROR, "Can not calloc object file : %s",
			     filename);
			return 4;
		}

#ifndef HAVE_FINCORE
		/* Affect vec with mincore */
		if (mincore(pa, st.st_size, vec) != 0)
		{
			munmap(pa, st.st_size);
			elog(ERROR, "mincore(%p, %lld, %p): %s\n",
			     pa, (long long int)st.st_size, vec, strerror(errno));
#else
		/* Affect vec with fincore */
		if (fincore(fd, 0, st.st_size, vec) != 0)
		{
			elog(ERROR, "fincore(%u, 0, %lld, %p): %s\n",
			     fd, (long long int)st.st_size, vec, strerror(errno));
#endif
			free(vec);
			FreeFile(fp);
			return 5;
		}

		/*
		 * prepare the bit string
		 */
		bitlen = FINCORE_BITS * ((st.st_size+pgfncr->pageSize-1)/pgfncr->pageSize);
		len = VARBITTOTALLEN(bitlen);
		/*
		 * set to 0 so that *r is always initialised and string is zero-padded
		 * XXX: do we need to free that ?
		 */
		pgfncr->databit = (VarBit *) palloc0(len);
		SET_VARSIZE(pgfncr->databit, len);
		VARBITLEN(pgfncr->databit) = bitlen;

		r = VARBITS(pgfncr->databit);
		x = HIGHBIT;

		/* handle the results */
		for (pageIndex = 0; pageIndex <= pgfncr->rel_os_pages; pageIndex++)
		{
			// block in memory
			if (vec[pageIndex] & FINCORE_PRESENT)
			{
				pgfncr->pages_mem++;
				*r |= x;
				if (FINCORE_BITS > 1)
				{
					if (vec[pageIndex] & FINCORE_DIRTY)
					{
						pgfncr->pages_dirty++;
						*r |= (x >> 1);
						/* we flag to detect contigous blocks in the same state */
						if (flag_dirty)
							pgfncr->group_dirty++;
						flag_dirty = 0;
					}
					else
						flag_dirty = 1;
				}
示例#3
0
/*
 * pgfadvise_file
 */
static int
pgfadvise_loader_file(char *filename,
					  bool willneed, bool dontneed, VarBit *databit,
					  pgfloaderStruct *pgfloader)
{
	bits8	*sp;
	int		bitlen;
	bits8	x;
	int		i, k;

	/*
	 * We use the AllocateFile(2) provided by PostgreSQL.  We're going to
	 * close it ourselves even if PostgreSQL close it anyway at transaction
	 * end.
	 */
	FILE	*fp;
	int	fd;
	struct stat st;

	/*
	 * OS things : Page size
	 */
	pgfloader->pageSize = sysconf(_SC_PAGESIZE);

	/*
	 * we count the action we perform
	 * both are theorical : we don't know if the page was or not in memory
	 * when we call posix_fadvise
	 */
	pgfloader->pagesLoaded		= 0;
	pgfloader->pagesUnloaded	= 0;

	/*
	 * Fopen and fstat file
	 * fd will be provided to posix_fadvise
	 * if there is no file, just return 1, it is expected to leave the SRF
	 */
	fp = AllocateFile(filename, "rb");
	if (fp == NULL)
                return 1;

	fd = fileno(fp);
	if (fstat(fd, &st) == -1)
	{
		FreeFile(fp);
		elog(ERROR, "pgfadvise_loader: Can not stat object file: %s", filename);
		return 2;
	}

	elog(DEBUG1, "pgfadvise_loader: working on %s", filename);

	bitlen = VARBITLEN(databit);
	sp = VARBITS(databit);
	for (i = 0; i < bitlen - BITS_PER_BYTE; i += BITS_PER_BYTE, sp++)
	{
		x = *sp;
		/*  Is this bit set ? */
		for (k = 0; k < BITS_PER_BYTE; k++)
		{
			if (IS_HIGHBIT_SET(x))
			{
				if (willneed)
				{
					(void) posix_fadvise(fd,
					                     ((i+k) * pgfloader->pageSize),
					                     pgfloader->pageSize,
					                     POSIX_FADV_WILLNEED);
					pgfloader->pagesLoaded++;
				}
			}
			else if (dontneed)
			{
				(void) posix_fadvise(fd,
				                     ((i+k) * pgfloader->pageSize),
				                     pgfloader->pageSize,
				                     POSIX_FADV_DONTNEED);
				pgfloader->pagesUnloaded++;
			}

			x <<= 1;
		}
	}
	/*
	 * XXX this copy/paste of code to finnish to walk the bits is not pretty
	 */
	if (i < bitlen)
	{
		/* print the last partial byte */
		x = *sp;
		for (k = i; k < bitlen; k++)
		{
			if (IS_HIGHBIT_SET(x))
			{
				if (willneed)
				{
					(void) posix_fadvise(fd,
					                     (k * pgfloader->pageSize),
					                     pgfloader->pageSize,
					                     POSIX_FADV_WILLNEED);
					pgfloader->pagesLoaded++;
				}
			}
			else if (dontneed)
			{
				(void) posix_fadvise(fd,
				                     (k * pgfloader->pageSize),
				                     pgfloader->pageSize,
				                     POSIX_FADV_DONTNEED);
				pgfloader->pagesUnloaded++;
			}
			x <<= 1;
		}
	}
	FreeFile(fp);

	/*
	 * OS things : Pages free
	 */
	pgfloader->pagesFree = sysconf(_SC_AVPHYS_PAGES);

	return 0;
}