⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpi.c

📁 uClinux下用的数据库
💻 C
📖 第 1 页 / 共 3 页
字号:
		direction;{	cpi_cls	clusterBuf;	cpi_ch	*cacheEntry;	char	*cp,		*cp1,		*pagePtr;	/*	** Shuffle all the headers in the page one slot starting	** at the specified header.  	*/	if (cpiDebug)	{		printf("DEBUG  shiftHeaderPage %s Cluster %d from %d\n",			direction == CPI_SHIFT_UP?"up":"down",			clusterNum, headerNum);	}	cacheEntry = readPage(idx, CPI_CLS_PAGE(idx, clusterNum));	getCluster(idx, cacheEntry, clusterNum, &clusterBuf);	pagePtr = cacheEntry->ptr;	if (direction == CPI_SHIFT_UP)	{		cp = pagePtr + CPI_CLS_SIZE(idx) + 			(headerNum * CPI_HDR_SIZE(idx));		cp1 = cp + CPI_HDR_SIZE(idx);		bcopy(cp,cp1,(CPI_SBK(idx)->hdrsPerPage-headerNum-1) * 			CPI_HDR_SIZE(idx));	}	else	{		headerNum ++;		if (headerNum < *clusterBuf.numHeaders)		{			cp = pagePtr + CPI_CLS_SIZE(idx) + 				(headerNum * CPI_HDR_SIZE(idx));			cp1 = cp - CPI_HDR_SIZE(idx);			bcopy(cp,cp1,(CPI_SBK(idx)->hdrsPerPage-headerNum-1) * 				CPI_HDR_SIZE(idx));		}	}	*(clusterBuf.numHeaders) += direction;}static void setMaxValue(idx, clusterNum, headerNum, key, flag)	cpi	*idx;	int	headerNum,		clusterNum;	char	*key;	int	flag;{	int	res = 0;	cpi_cls	clusterBuf;	cpi_hdr	headerBuf;	cpi_ch	*cachePtr;	/*	** Reset the maxValue of the page header if required. If the	** data page is empty we set the value regardless.	*/	cachePtr = readPage(idx, CPI_CLS_PAGE(idx,clusterNum));	getHeader(idx, cachePtr, clusterNum, headerNum, &headerBuf);	if (*headerBuf.numRecords > 0 && flag == CPI_IF_NEEDED)	{		compareValues(idx, key, headerBuf.maxValue, res);		if (res <= 0)		{			return;		}	}	if (cpiDebug)	{		printf("DEBUG  Max value for hdr %d, page %d set to ",			headerBuf.headerNum, *headerBuf.pageNum);		printValue(key, CPI_SBK(idx)->keyType);		printf("\n");	}	bcopy(key, headerBuf.maxValue, CPI_SBK(idx)->keySize);	/*	** If this is the last header in the cluster then reset the	** cluster's max value too	*/	getCluster(idx,cachePtr,clusterNum,&clusterBuf);	if (headerNum == *(clusterBuf.numHeaders) - 1)	{		bcopy(key, clusterBuf.maxValue, CPI_SBK(idx)->keySize);		if (cpiDebug)		{			printf("DEBUG  Max value for cluster %d set to ",				clusterNum);			printValue(key, CPI_SBK(idx)->keyType);			printf("\n");		}	}}static void resetMaxValue(idx, clusterNum, headerNum)	cpi	*idx;	int	headerNum,		clusterNum;{	cpi_nod	nodeBuf;	cpi_hdr	headerBuf;	cpi_ch	*cachePtr;	int	pageNum;	cachePtr = readPage(idx, CPI_CLS_PAGE(idx,clusterNum));		getHeader(idx, cachePtr, clusterNum, headerNum, &headerBuf);	pageNum = *headerBuf.pageNum;	cachePtr = readPage(idx, pageNum);	getRecord(idx, cachePtr, clusterNum, headerNum,  		*headerBuf.numRecords - 1, &nodeBuf);	if (cpiDebug)	{		printf("DEBUG  Reset Max for hdr %d:%d page %d\n", 			clusterNum,headerNum, pageNum);	}	setMaxValue(idx, clusterNum, headerNum, nodeBuf.key, CPI_FORCE);}static void splitClusters(idx, cluster1, cluster2)	cpi	*idx;	int	cluster1, cluster2;{	cpi_cls	cluster1Buf, cluster2Buf;	cpi_ch	*cache1, *cache2;	char	*ptr1, *ptr2, *cp;	int	spare,		splitDest;	cache1 = readPage(idx, CPI_CLS_PAGE(idx, cluster1));	cache2 = readPage(idx, CPI_CLS_PAGE(idx, cluster2));	getCluster(idx, cache1, cluster1, &cluster1Buf);	getCluster(idx, cache2, cluster2, &cluster2Buf);	ptr1 = cache1->ptr + CPI_CLS_SIZE(idx);	ptr2 = cache2->ptr + CPI_CLS_SIZE(idx);	if (*cluster1Buf.numHeaders < *cluster2Buf.numHeaders)	{		spare = CPI_SBK(idx)->hdrsPerPage - *cluster1Buf.numHeaders;		splitDest = 1;	}	else	{		spare = CPI_SBK(idx)->hdrsPerPage - *cluster2Buf.numHeaders;		splitDest = 2;	}	if (cpiDebug)	{		printf("DEBUG  splitClusters : Cls1=%d, Cls2=%d, ",			cluster1, cluster2);		printf("spare slots=%d, dest=hdr%d\n",			spare, splitDest);	}	/*	** Copy (spare / 2) headers from the full cluster to the other	*/	if (splitDest == 1)	{		cp = ptr1 + (*cluster1Buf.numHeaders * CPI_HDR_SIZE(idx));		bcopy(ptr2, cp, (spare / 2) * CPI_HDR_SIZE(idx));		cp = ptr2 + ((spare / 2) * CPI_HDR_SIZE(idx));		bcopy(cp,ptr2,(*cluster2Buf.numHeaders - 			(spare / 2)) * CPI_HDR_SIZE(idx));		*(cluster1Buf.numHeaders) += spare / 2;		*(cluster2Buf.numHeaders) -= spare / 2;	}	else	{		cp = ptr2;		bcopy(cp, cp + (spare / 2 * CPI_HDR_SIZE(idx)), 			*cluster2Buf.numHeaders * CPI_HDR_SIZE(idx));		cp = ptr1 + ((*cluster1Buf.numHeaders - (spare / 2)) 			* CPI_HDR_SIZE(idx));		bcopy(cp, ptr2, spare / 2 * CPI_HDR_SIZE(idx)); 		*(cluster1Buf.numHeaders) -= spare / 2;		*(cluster2Buf.numHeaders) += spare / 2;	}	/*	** The maxValue of the clusters may have changed so force a reset	*/	resetMaxValue(idx, cluster1, *cluster1Buf.numHeaders - 1);	resetMaxValue(idx, cluster2, *cluster2Buf.numHeaders - 1);	if (cpiDebug)	{		printCluster(idx, &cluster1Buf);		printCluster(idx, &cluster2Buf);	}}static void splitPages(idx, cluster1, header1, cluster2, header2)	cpi	*idx;	int	cluster1, header1,		cluster2, header2;{	cpi_hdr	header1Buf, header2Buf;	cpi_ch	*cachePtr1, *cachePtr2,		*nodeCachePtr1, *nodeCachePtr2;	char	*page1Ptr, *page2Ptr,		*cp;	int	spare,		splitDest;	cachePtr1 = readPage(idx, CPI_CLS_PAGE(idx, cluster1));	getHeader(idx, cachePtr1, cluster1, header1, &header1Buf);	cachePtr2 = readPage(idx, CPI_CLS_PAGE(idx, cluster2));	getHeader(idx, cachePtr2, cluster2, header2, &header2Buf);	if (*header1Buf.numRecords < *header2Buf.numRecords)	{		spare = CPI_SBK(idx)->recsPerPage - *header1Buf.numRecords;		splitDest = 1;	}	else	{		spare = CPI_SBK(idx)->recsPerPage - *header2Buf.numRecords;		splitDest = 2;	}	nodeCachePtr1 = readPage(idx, *header1Buf.pageNum);	nodeCachePtr2 = readPage(idx, *header2Buf.pageNum);	page1Ptr = nodeCachePtr1->ptr;	page2Ptr = nodeCachePtr2->ptr;	if (cpiDebug)	{		printf("DEBUG  splitPages : hdr1=%d:%d, ", cluster1, header1);		printf("hdr2=%d:%d, spare slots=%d, dest=hdr%d\n",			cluster2, header2, spare, splitDest);	}	/*	** Copy (spare / 2) records from the full page to the other	*/	if (splitDest == 1)	{		cp = page1Ptr + (*header1Buf.numRecords * CPI_REC_SIZE(idx));		bcopy(page2Ptr, cp, (spare / 2) * CPI_REC_SIZE(idx));		cp = page2Ptr + ((spare / 2) * CPI_REC_SIZE(idx));		bcopy(cp,page2Ptr,(*header2Buf.numRecords - 			(spare / 2)) * CPI_REC_SIZE(idx));		*(header1Buf.numRecords) += spare / 2;		*(header2Buf.numRecords) -= spare / 2;	}	else	{		cp = page2Ptr;		bcopy(cp, cp + (spare / 2 * CPI_REC_SIZE(idx)), 			*header2Buf.numRecords * CPI_REC_SIZE(idx));		cp = page1Ptr + ((*header1Buf.numRecords - (spare / 2)) 			* CPI_REC_SIZE(idx));		bcopy(cp, page2Ptr, spare / 2 * CPI_REC_SIZE(idx)); 		*(header1Buf.numRecords) -= spare / 2;		*(header2Buf.numRecords) += spare / 2;	}	/*	** The maxValue of the pages may have changed so	** force a reset in the headers.	*/	resetMaxValue(idx, cluster1, header1);	resetMaxValue(idx, cluster2, header2);	if (cpiDebug)	{		printHeader(idx, &header1Buf);		printHeader(idx, &header2Buf);	}}static void createSpaceForCluster(idx, clusterNum)	cpi	*idx;	int	clusterNum;{	cpi_cls	clusterBuf;	cpi_hdr	headerBuf;	cpi_ch	*cachePtr;	int	foundRoom = 0,		curCluster,		cluster1 = 0, 		cluster2 = 0, 		curHeader,		freeSpace;	cpi_ch	*cacheEntry1,		*cacheEntry2;	if (cpiDebug)	{		printf("DEBUG  createSpaceForCluster( %d)\n",clusterNum);	}	/*	** If there's room in a neighbour cluster then grab half	** of it.  Try the left neighbour first if there is one.	*/	if (clusterNum > 0)	{		curCluster = clusterNum - 1;		cachePtr = readPage(idx, CPI_CLS_PAGE(idx,curCluster));		getCluster(idx, cachePtr, curCluster,&clusterBuf);		freeSpace = CPI_SBK(idx)->hdrsPerPage - *clusterBuf.numHeaders;		if (freeSpace > CPI_SBK(idx)->hdrsPerPage / 8 && freeSpace > 3)		{			cluster1 = curCluster;			cluster2 = clusterNum;			foundRoom = 1;		}	}	/*	** How about the right neighbour	*/	if ( ! foundRoom)	{		if (clusterNum < CPI_SBK(idx)->numClusters -1 )		{			curCluster = clusterNum + 1;			cachePtr=readPage(idx,CPI_CLS_PAGE(idx,curCluster));			getCluster(idx, cachePtr, curCluster,&clusterBuf);			freeSpace = CPI_SBK(idx)->hdrsPerPage - 				*clusterBuf.numHeaders;			if (freeSpace > CPI_SBK(idx)->hdrsPerPage / 8 && 				freeSpace > 3)			{				cluster1 = clusterNum;				cluster2 = curCluster;				foundRoom = 1;			}		}	}	/*	** If there's no room near here then we have to create a new cluster.	** Drop a new cluser on the end of the file and roll the clusters	** down one from clusterNum.	*/	if ( ! foundRoom)	{		curCluster = CPI_SBK(idx)->numClusters - 1;		initialiseCluster(idx, curCluster + 1);		cacheEntry2 = readPage(idx,CPI_CLS_PAGE(idx,curCluster+1));		while(curCluster > clusterNum)		{			cacheEntry1 = readPage(idx,				CPI_CLS_PAGE(idx,curCluster));			bcopy(cacheEntry1->ptr, cacheEntry2->ptr, 				CPI_SBK(idx)->pageSize);			getCluster(idx,cacheEntry2,curCluster+1,&clusterBuf);			*clusterBuf.pageNum=CPI_CLS_PAGE(idx,curCluster+1);			cacheEntry2 = cacheEntry1;			curCluster--;		}		cluster1 = clusterNum;		cluster2 = clusterNum + 1;		/*		** Zero out the values in the old cluster so we can		** reuse it as a fresh page		*/		cachePtr = readPage(idx, CPI_CLS_PAGE(idx,cluster2));		getCluster(idx, cachePtr, cluster2, &clusterBuf);		curHeader = 0;		while(curHeader < *clusterBuf.numHeaders)		{			getHeader(idx, cachePtr, cluster2, curHeader, 				&headerBuf);			*headerBuf.numRecords = 0;			*headerBuf.pageNum = 0;			curHeader++;		}		*clusterBuf.numHeaders = 0;	}	splitClusters(idx, cluster1, cluster2);}static void createSpaceForHeader(idx, clusterNum, headerNum)	cpi	*idx;	int	clusterNum,		headerNum;{	cpi_cls	clusterBuf;	cpi_hdr	headerBuf;	cpi_ch	*cachePtr;	int	foundRoom = 0,		curCluster, curHeader,		cluster1 = 0, header1 = 0,		cluster2 = 0, header2 = 0,		freeSpace,		validPage;	if (cpiDebug)	{		printf("DEBUG  createSpaceForHeader( %d,%d)\n",clusterNum,			headerNum);	}	/*	** If there's room in a neighbour page then grab half	** of it.  Try the left neighbour first.	*/	curCluster = clusterNum;	curHeader = headerNum;	validPage = 1;	if (curHeader == 0)	{		if (curCluster > 0)		{			curCluster --;			cachePtr = readPage(idx,CPI_CLS_PAGE(idx,curCluster));			getCluster(idx,cachePtr,curCluster,&clusterBuf);			curHeader = *clusterBuf.numHeaders - 1;		}		else		{			validPage = 0;		}	}	else	{		curHeader --;	}	if (validPage)	{		cachePtr = readPage(idx,CPI_CLS_PAGE(idx,curCluster));		getHeader(idx, cachePtr, curCluster, curHeader, &headerBuf);		freeSpace = CPI_SBK(idx)->recsPerPage - *headerBuf.numRecords;		if (freeSpace > CPI_SBK(idx)->recsPerPage / 4 &&			freeSpace > 3)		{			cluster1 = curCluster;			header1 = curHeader;			cluster2 = clusterNum;			header2 = headerNum;			foundRoom = 1;		}	}	/*	** How about the right neighbour	*/	if ( ! foundRoom)	{		curCluster = clusterNum;		curHeader = headerNum;		validPage = 1;		cachePtr = readPage(idx,CPI_CLS_PAGE(idx,curCluster));		getCluster(idx,cachePtr,curCluster,&clusterBuf);		if (curHeader == CPI_SBK(idx)->hdrsPerPage - 1)		{			curCluster ++;			curHeader = 0;			if (curCluster == CPI_SBK(idx)->numClusters)			{				validPage = 0;			}		}		else		{			curHeader ++;			if (curHeader == *clusterBuf.numHeaders)			{				validPage = 0;			}		}		if (validPage)		{			cachePtr = readPage(idx,CPI_CLS_PAGE(idx,curCluster));			getHeader(idx,cachePtr,curCluster,curHeader,&headerBuf);			freeSpace = CPI_SBK(idx)->recsPerPage - 				*headerBuf.numRecords;			if (freeSpace > CPI_SBK(idx)->recsPerPage / 4 &&				freeSpace > 3)			{				cluster2 = curCluster;				header2 = curHeader;				cluster1 = clusterNum;				header1 = headerNum;				foundRoom = 1;			}		}	}	/*	** If there's no room near here then we have to create a new page.	** Note, the above code will leave curCluster and curHeader set	** to the header directly after the one we are working on.  If	** the page wasn't valid before, it will be after the shiftHeader()	*/	if ( ! foundRoom)	{		int	tmpPageNum;		getFreePage(idx, &tmpPageNum);		shiftHeaderPage(idx, clusterNum, headerNum, CPI_SHIFT_UP);		cachePtr = readPage(idx,CPI_CLS_PAGE(idx,clusterNum));		getHeader(idx, cachePtr, clusterNum, headerNum, &headerBuf);		*headerBuf.pageNum = tmpPageNum;		*headerBuf.numRecords = 0;		cluster2 = curCluster;		header2 = curHeader;		cluster1 = clusterNum;		header1 = headerNum;	}	splitPages(idx, cluster1, header1, cluster2, header2);}/*******************************************************************************************************************************************************                        INTERFACE ROUTINES*****************************************************************************************************************************************************//*static void apiInit(){}*/#define	apiInit()int cpiCreate(path, mode, keySize, keyType, flags, envPtr)        char    *path;        int     mode,                keySize,                keyType,                flags;	cpi_env	*envPtr;{        int     fd;        cpi_sbk sbk;	cpi	idx;        /*        ** Create the actual file        */	apiInit();        fd = open(path,O_RDWR | O_CREAT, mode);        if (fd < 0)        {                return(-1);        }        /*        ** Setup the basic superblock info        */        strcpy(sbk.fileType,"#! Clustered Page Index Format");        sbk.magic = CPI_MAGIC;        sbk.version = CPI_VERSION;        sbk.keyType = keyType;        if (keyType == CPI_CHAR)                keySize++;        sbk.keySize = keySize;	/*	** Now the important stuff.  Set the page size and ensure the	** mapping size is VM page aligned	*/	sbk.pageSize = 0;	if (envPtr)		sbk.pageSize = envPtr->pageSize;	if (sbk.pageSize == 0)		sbk.pageSize = getpagesize();	sbk.cacheSize = 0;	if (envPtr)		sbk.cacheSize = envPtr->cacheSize;	if (sbk.cacheSize == 0)		sbk.cacheSize = CPI_DEFAULT_CACHE;	sbk.vmPageSize = getpagesize();	if (sbk.pageSize % sbk.vmPageSize != 0)	{		sbk.mapSize = ((sbk.pageSize / sbk.vmPageSize) + 1) *			sbk.vmPageSize;	}	else	{		sbk.mapSize = sbk.pageSize;	}#	ifdef FORCE_SMALL_PAGES	sbk.recsPerPage = 5;	sbk.hdrsPerPage = 6;#	else	sbk.recsPerPage = (sbk.pageSize / (keySize + sizeof(u_int)));	sbk.hdrsPerPage = (sbk.pageSize - (keySize + 2 * sizeof(u_int))) / 		(keySize + 2 * sizeof(u_int));#	endif	sbk.numRecords = 0;	sbk.numKeys = 0;	sbk.numClusters = 1;	sbk.cacheLookups = 0;	sbk.cacheHits = 0;	sbk.freeList = 2;	        if (write(fd,&sbk,sizeof(sbk)) < sizeof(sbk))        {                 close(fd);                unlink(path);                return(-1);        }       	/*	** Initialise the first cluster	*/	idx.opaque = &sbk;	idx.fd = fd;	initialiseCluster(&idx, 0);	close(fd);	return(0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -