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

📄 bfh.c

📁 btree的实现源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		return FAILED;	}	/* Is the request on a user block boundry ? */	if( ( (block_addr - (2*BFHBLOCK) -1) % bfh->block_size ) != 0){		Debug( "Invalid block address\n");		return FAILED;	}	/* Go to the requested block's switch byte */	if(lseek(bfh->file_fd, block_addr - 1L,0) == -1L){		Debug( "Cant seek\n");		return FAILED;	}	if(read(bfh->file_fd, &inuse, 1) == -1){		Debug( "Cant read key in\n");		return FAILED;	}	inuse &= BFHBLOCKINUSE;	/* User can only write a block they are already using */	if(!inuse){		Debug( "BfhWriteBlock attempt to overwrite free list entry\n");		return FAILED;	}	/* Now we are in position over the user block */	if(write(bfh->file_fd,ptr,bfh->block_size-1) == -1){		Debug( "Cant write bdata\n");		return FAILED;	}	bfh->date_updated = time(NULL);	return SUCCESS;}/* NAME:	ReadBlock DESCRIPTION: 	Read the block at the user specified address RETURN:	SUCCESS or FAILED or EMPTY*/int BfhReadBlock(	BFH * bfh, /* pointer to descriptor */			char * ptr, /* address in which to place data */			long block_addr /* block id */){  	char cswitch;	Trace("BfhReadBlock(%x, %x, %ld)\n",		(unsigned)bfh, (unsigned)ptr, block_addr);	/* Is the request beyond the last block in the file? */	if( block_addr > ((bfh->add_block_addr - bfh->block_size) + 1)){		Debug( "Cant read beyond end of file\n");		return FAILED;	}	/* Is the request below the first block in the file? */	if(block_addr < ((2*BFHBLOCK) + 1) ){		Debug( "Invalid block address\n");		return FAILED;	}	/* Is the request on a user block boundry ? */	if( ( (block_addr - (2*BFHBLOCK) -1) % bfh->block_size ) != 0){		Debug( "Invalid block address\n");		return FAILED;	}	/* Go to the switch byte for the block */	if(lseek(bfh->file_fd, block_addr - 1L,0) == -1L){		Debug( "Cant seek\n");		return FAILED;	}	if(read(bfh->file_fd,&cswitch,1) != 1) {		Debug( "Cant read switch\n");		return FAILED;	}	/* If in use, return day, else return EMPTY */	if(cswitch & BFHBLOCKINUSE){		if(read(bfh->file_fd,ptr,bfh->block_size-1) != (bfh->block_size-1)) {			Debug( "Cant read bdata\n");			return FAILED;		}	}else{		return EMPTY;	}	return SUCCESS;}/* NAME:	NewBlock DESCRIPTION: 	Get the first empty block, or initialize a new block		and return its user address RETURN:	The user address ofthe file of a new block, or the value		-1L on failure*/long BfhNewBlock(BFH * bfh /* poiner to bfh descriptor */){	struct free_block_id free_list_id;	long blocknumber;	char cswitch = 0;	int status;	Trace("BfhNewBlock(%x)\n", (unsigned)bfh);	if(bfh==NULL){		Debug("NULL bfh\n");		return -1L;	}	/* This Case:  No free block in list */	if(bfh->first_free_block_addr == -1L){		if(lseek(bfh->file_fd,bfh->add_block_addr,SEEK_SET) == -1L){			Debug("Cant lseek\n");			return -1L;		}		/* put the switch into place */		cswitch = bfh->mask | BFHBLOCKINUSE;		if(write(bfh->file_fd,&cswitch,1) != 1){ 			Debug( "Cant write\n");			return -1L;		}		if((status=write(bfh->file_fd,bfh->empty_rec,bfh->block_size)) != bfh->block_size){ 			Debug( "wrote %d bytes from %d blank bytes\n", status,bfh->block_size);			return -1L;		}		blocknumber = bfh->add_block_addr;		bfh->add_block_addr += bfh->block_size;		return ( blocknumber + 1L );	}	/* where is the next one?, save it */	blocknumber = bfh->first_free_block_addr;	/* This Case: Only one free block*/	if(bfh->first_free_block_addr == bfh->last_free_block_addr){		bfh->first_free_block_addr = -1L;		bfh->last_free_block_addr = -1L;		if(lseek(bfh->file_fd,blocknumber,0) == -1L){			Debug("Cant lseek\n");			return -1L;		}		/* put the switch into place */		cswitch = bfh->mask | BFHBLOCKINUSE;		if(write(bfh->file_fd,&cswitch,1) != 1){ 			Debug( "Cant write\n");			return -1L;		}		return (blocknumber + 1L) ;	}        /* Otherwise there must be more than one*/        /* This Case: Multiple free blocks*/	/* Get the free list info */	if(lseek(bfh->file_fd,bfh->first_free_block_addr + 1,0) == -1L) { 		Debug( "Cant seek\n");		return -1L;	}	if(read(bfh->file_fd,&free_list_id,sizeof(struct free_block_id)) 		!= sizeof(struct free_block_id) ){		Debug( "Cant read\n");		return -1L;	}	/* We'll give the user the first free block on list */	bfh->first_free_block_addr = free_list_id.next_block;        /* Go to the next block and mark it as the first*/	if(lseek(bfh->file_fd,bfh->first_free_block_addr+1,0) == -1L){ 		Debug( "Cant seek\n");		return -1L;        }	if( read(bfh->file_fd,&free_list_id,sizeof(struct free_block_id)) 		!= sizeof(struct free_block_id) ){		Debug( "Cant read\n");		return -1L;	}	/* Change it */       	free_list_id.previous_block = -1L;	/* Reposition */	if(lseek(bfh->file_fd,bfh->first_free_block_addr+1,0) == -1L){ 		Debug( "Cant seek\n");		return -1L;        }	/* write it back */	if( write(bfh->file_fd,&free_list_id,sizeof(struct free_block_id)) 		!= sizeof(struct free_block_id) ){		Debug( "Cant write\n");		return -1L;	}	/* set the switch */	if(lseek(bfh->file_fd,blocknumber,0) == -1L){		Debug("Cant lseek\n");		return -1L;	}	/* put the switch into place */	cswitch = bfh->mask | BFHBLOCKINUSE;	if(write(bfh->file_fd,&cswitch,1) != 1){ 		Debug( "Cant write\n");		return -1L;	}	return (blocknumber + 1L);}/* end BfhNewBlock(BFH * bfh) *//* NAME:	FreeBlock DESCRIPTION:	Add the block at the designated address to the free list RETURN:	SUCCESS or FAIL*/int BfhFreeBlock(BFH * bfh /*poiner to bfh descriptor */, 		long user_address /* block ID to free */){	struct free_block_id free_list_id;	long old_last_block, old_first_block;	char cswitch;	long address;	Trace("BfhFreeBlock(%x, %ld)\n", (unsigned)bfh, user_address);	address = --user_address;	/* Is the request beyond the last block in the file? */	if( address > ((bfh->add_block_addr - bfh->block_size) + 1)){		Debug( "Request beyond end of file\n");		return FAILED;	}	/* Is the request below the first block in the file? */	if(address < (2*BFHBLOCK) ){		Debug( "Invalid block address\n");		return FAILED;	}	/* Is the request on a user block boundry ? */	if(	    (((address - (2*BFHBLOCK)) + bfh->block_size)  % bfh->block_size ) 			!= 0){		Debug( "Invalid block address\n");		return FAILED;	}	old_last_block = bfh->last_free_block_addr;	/* if there is already a free block mark the old one*/	/* go to the last free block*/	cswitch = 0;	if(bfh->last_free_block_addr != -1L) {		/* if it is a high block, put it on the end of */		/* the list*/		if(address > bfh->first_free_block_addr){			if(lseek(bfh->file_fd,bfh->last_free_block_addr+1,0) == -1L){ 				Debug("Couldnt seek\n");				return FAILED;			}			if(read(bfh->file_fd,&free_list_id,sizeof(struct free_block_id)) != sizeof(struct free_block_id)) { 				Debug("Read failure\n");				return FAILED;			}			/* mark it with the next block id*/			free_list_id.next_block = address ;			/* write it back*/			if(lseek(bfh->file_fd,bfh->last_free_block_addr+1,0) == -1L) {				Debug("Couldnt seek\n");				return FAILED;			}			if(write(bfh->file_fd,&free_list_id,sizeof(struct free_block_id)) != sizeof(struct free_block_id)) { 				Debug( "Couldnt write\n");				return FAILED;			}			/* mark the new last block*/			free_list_id.previous_block = old_last_block;			free_list_id.next_block = -1L;			bfh->last_free_block_addr = address;		}else{			/* if it is a low block, put it on the front of */			/* the list*/			old_first_block = bfh->first_free_block_addr;			if(lseek(bfh->file_fd,bfh->first_free_block_addr+1,0) == -1L){       				Debug("Couldnt seek\n");       				return FAILED;			}			if(read(bfh->file_fd,&free_list_id,				sizeof(struct free_block_id)) != 				sizeof(struct free_block_id)) 			{				Debug("Read failure\n");				return FAILED;			}			/* mark it with the next block id*/			free_list_id.previous_block = address ;			/* write it back*/			if(lseek(bfh->file_fd,bfh->first_free_block_addr+1,0) == -1L) {				Debug("Couldnt seek\n");				return FAILED;			}			if(write(bfh->file_fd,&free_list_id,				sizeof(struct free_block_id)) != 				sizeof(struct free_block_id)) 			{				Debug( "Couldnt write\n");				return FAILED;			}			/* mark the new last block*/			free_list_id.previous_block = -1;			free_list_id.next_block = old_first_block;			bfh->first_free_block_addr = address;		}	}else{			/*bfh->last_free_block_addr == -1L */		/* the new one will be the only one*/		if( bfh->last_free_block_addr == bfh->first_free_block_addr ){			bfh->first_free_block_addr = address;			bfh->last_free_block_addr = address;			free_list_id.previous_block = -1L;			free_list_id.next_block = -1L;		}else{			Debug("Cant be a first free block without a last free block\n");			return FAILED;		}	} 	/* mark the last block*/	/* set up the free list structure*/	/* mark the new last block*/	if(lseek(bfh->file_fd,address,0) == -1L) {		Debug("Couldnt seek\n");		return FAILED;	}	if(write(bfh->file_fd,&cswitch,1) != 1) { 		Debug( "Couldnt write\n");		return FAILED;	}	if(write(bfh->file_fd,&free_list_id,sizeof(struct free_block_id)) != sizeof(struct free_block_id)) { 		Debug( "Couldnt write\n");		return FAILED;	}	return SUCCESS;}	/* NAME:	AddrBlock DESCRIPTION:	Convert 0 based  block number to a user block address		representing the data block point RETURN:	long address*/long BfhAddrBlock(BFH * bfh, /* pointer to bfh descriptor */ 		  int i /* block sequential number */){ /* First file block is 0*/	long l;	Trace("BfhAddrBlock(%x, %d)\n", (unsigned)bfh, i);	l = ( (2*BFHBLOCK) + ((long)i * bfh->block_size) + 1L);	return ( (l < bfh->add_block_addr)?l:-1L );}/* NAME:	BfhFullBlock DESCRIPTION:	provided a block number, determine if the block is free RETURN:	1 for a used block, 0 for a free block, -1 for an error*/int BfhFullBlock(BFH * bfh, /* pointer to block file descriptor */		 int blocknum /* block sequential number */) { 	long posn;	char cswitch;	Trace("BfhFullBlock(%x, %d)\n", (unsigned)bfh, blocknum);	posn = BfhAddrBlock(bfh,blocknum);	if(posn == -1L){		Debug("Invalid position\n");		return -1;	}	if(lseek(bfh->file_fd,posn-1,0) == -1L) {		Debug( "Couldnt seek\n");		return -1;	}	if(read(bfh->file_fd,&cswitch,1) != 1) {		Debug( "Couldnt read\n");		return -1;	}	return ( cswitch & BFHBLOCKINUSE);}/*.****************************************************** Function Name: 	PrintBfhDescriptor** Access from:** Synopsis:** Arguments:** Description:** Return:** History:	Created from B+Tree in C++, 1995** Copr 1991,1992,1995  Tue Mar 21 15:57:56 EST 1995 Larry A. Walker**  Modified:*******************************************************/void PrintBfhDescriptor(BFH * bf /* pointer to block file descriptor */){	if(bf == NULL){		View("NULL Bfh\n");		return;	}	View("\t\tBfh Info Bfh = %x\n", (unsigned)bf);	View("version %s, file_fd %d, file_name %s\n", 		(char *)(bf->version), bf->file_fd, (char *)(bf->file_name));	View("magic %ld, block_size %d, mask %d\n", 		bf->magic, bf->block_size, bf->mask);	View("date_created %sdate_opened %sdate_updated %s\n", 		ctime(&(bf->date_created)) , ctime(&(bf->date_opened)) , ctime(&(bf->date_updated)));	View("first_free_block_addr %ld, last_free_block_addr %ld, \nadd_block_addr %ld\n", 		bf->first_free_block_addr,bf->last_free_block_addr,bf->add_block_addr );		} /*end  "PrintBfhDescriptor" */

⌨️ 快捷键说明

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