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

📄 btree.c

📁 btree的实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				Debug("Couldnt write block\n");				return FAIL;			}		}	}	btree->vector = -1;	btree->blocks_to_flush = 0;	btree->active_node = NULL;return SUCCESS;} /* FlushHierarchy*//*// NAME: 	LoadHierarchyNode//// DESCRIPTION:	Load a node into hierarchy at the current vector//// RETURN:	SUCCESS or FAIL//*/int LoadHierarchyNode(BTREE * btree /* pointer to tree descriptor */,		             long n /* node number */){	Trace(" LoadHierarchyNode(%x,%ld)\n", (unsigned)btree, n);	if (btree->vector < -1) {		Debug("Invalid node vector\n");		return FAILED;		}	++btree->vector;	/* Want to create really huge b+trees?*//* law 2/4/94 */	if( (btree->vector + 1) > btree->ActiveHeight ){		btree->hierarchy_list = (struct HierarchyBlock *)			realloc((void *)btree->hierarchy_list,				( (btree->ActiveHeight+1)*sizeof(struct HierarchyBlock)) );		if(btree->hierarchy_list == NULL)			Debug("Insufficient available memory\n");		/* new block in hierarchy gets set clean*/		(btree->hierarchy_list+btree->ActiveHeight)->block_id = -1L;		(btree->hierarchy_list+btree->ActiveHeight)->state = CLEAN;		btree->ActiveHeight++;	}	if( ((btree->hierarchy_list+btree->vector)->state == DIRTY) && 		((btree->hierarchy_list+btree->vector)->block_id != n) ){			if(BfhWriteBlock(btree->bfh,(char*)&((btree->hierarchy_list+(btree->vector))->hierarchy_node), (btree->hierarchy_list+(btree->vector))->block_id) == FAIL){			Debug("Couldnt write block\n");			return FAIL;			}		}	if((btree->hierarchy_list+btree->vector)->block_id == n){		OpenKeyNode( btree,&(btree->hierarchy_list+btree->vector)->hierarchy_node);		if(btree->blocks_to_flush < (btree->vector + 1))			btree->blocks_to_flush = (btree->vector + 1);		return SUCCESS;		}	if(BfhReadBlock(btree->bfh,(char *)&(btree->hierarchy_list+btree->vector)->hierarchy_node,n) != 			SUCCESS){		btree->active_node = NULL;		Debug("Couldnt read block\n");		return FAIL;		}	OpenKeyNode( btree,&(btree->hierarchy_list+btree->vector)->hierarchy_node);	(btree->hierarchy_list+btree->vector)->block_id = n;	(btree->hierarchy_list+btree->vector)->state = CLEAN;	if(btree->blocks_to_flush < (btree->vector + 1))		btree->blocks_to_flush = (btree->vector + 1);	return SUCCESS;} /* LoadHierarchyNode*/	/*// NAME:	Parent//// DESCRIPTION:	Move up the hierarchy and make the parent node the new active//		node.//// RETURN:	Pointer to the parent node//*/static struct Node * Parent(BTREE * btree /* pointer to tree descriptor */){	Trace("Parent(%x)\n", (unsigned)btree);	if( btree->vector < 1 )		return NULL;	--btree->vector;	OpenKeyNode( btree,&(btree->hierarchy_list+btree->vector)->hierarchy_node);	return &((btree->hierarchy_list+btree->vector)->hierarchy_node);}/*// NAME:	KeyGroupSize//// DESCRIPTION:	Provides a means to determine the size of a key group//// RETURN:	integer size of the key group//*/int KeyGroupSize(BTREE * btree /* pointer to tree descriptor */,	         struct KeyGroup * ks /* An encapsolated key */){	int i;	Trace("KeyGroupSize(%x,%x)\n", (unsigned)btree, (unsigned)ks);	i = sizeof(long) + sizeof(ks->KeyData);	switch(btree->type_of_key){		case VAR_LNG_KEY:			i+=(int)ks->k.key[0]+1;/* law fix 1/29/94 */#ifdef ALIGN2                        	i += ( 2 - ( (i+2) % 2 ) );#endif#ifdef ALIGN4                        	i += ( 4 - ( (i+4) % 4 ) );#endif			break;		case FIX_LNG_KEY:		case LONG_KEY:		case DOUBLE_KEY:			i+=btree->fix_lng_key_lng;			break;		default:			Debug("Invalid KeyType\n");	}	return i;}	/* HERE --- can't allow this to calloc memory junk *//*// NAME:	CopyKey//// DESCRIPTION:	Copies the active_key into a store area, and returns a pointer//		to the area.  Calling programs cannot then corrupt the key.//// RETURN:	pointer to a key group//struct KeyGroup * CopyKey(BTREE * btree ){	Trace("CopyKey(%x)\n", (unsigned)btree);	if(btree->key_copy == NULL){		btree->key_copy = (struct KeyGroup *)calloc(1,sizeof(struct KeyGroup));		if(btree->key_copy == NULL){			Debug("Insufficient available memory\n");		}	}	mv_mem((char *)btree->active_key,(char *)btree->key_copy,KeyGroupSize(btree,btree->active_key));	return btree->key_copy;}*//*// NAME:	InsertNodeKeyGroup//// DESCRIPTION:	Submit a key group for insert into a node.  If the node//		is too full to accept the key, return FAIL, otherwise//		insert at the current position in the node.//// RETURN:	SUCCESS or FAIL.  A full node returns FAIL, while anything//		else inserts and returns SUCCESS. //*/static int  InsertNodeKeyGroup(BTREE * btree /* pointer to tree descriptor */,	   		struct KeyGroup * kg /* An encapsolated key */){	int i,active_posn;	Trace("InsertNodeKeyGroup(%x,%x)\n",		(unsigned)btree, (unsigned)kg);	i = KeyGroupSize(btree,kg);	if( (btree->block_size - btree->active_node->next_free_position ) < i ) {		return FAIL;  	}	active_posn = (char *)btree->active_key - (char *)btree->active_node;	mv_mem((char *)btree->active_node + active_posn, 		(char *)btree->active_node + active_posn + i,		btree->block_size - i - active_posn);	mv_mem((char *)kg,(char *)btree->active_node+active_posn,i);	btree->active_node->total_node_keys ++;	btree->active_node->next_free_position += i;	if(btree->vector != -1)		(btree->hierarchy_list+btree->vector)->state = DIRTY;	return SUCCESS;}/*// NAME:	InsertSpareKeyGroup//// DESCRIPTION:	This function is used to build the spare node.  Called//		repetively, this function inserts key groups into the //		spare node in the sequence provided, at the end of the//		list.//// RETURN:	SUCCESS or FAIL//*/static int  InsertSpareKeyGroup(BTREE * btree /* pointer to tree descriptor */,			 struct KeyGroup * kg /* An encapsolated key */,			 struct Node * spare_node /* Pointer to working spare */){	/* insert into the spare node, end position only*/	int i;	Trace("InsertSpareKeyGroup(%x,%x,%x)\n", (unsigned)btree, 		(unsigned)kg, (unsigned)spare_node);	i = KeyGroupSize(btree,kg);/*fprintf(stderr, "%d - ( %d + 1 ) <= %d\n",btree->block_size, spare_node->next_free_position, i);*/	if( (btree->block_size - spare_node->next_free_position ) < i ) {/*runtime_error(TRACE,__FILE__,__LINE__,"Node too full for insert");*/		return FAIL;	}  /* cant stuff any more here*/	mv_mem((char *)kg,(char *)spare_node+spare_node->next_free_position,i);	spare_node->total_node_keys ++;	spare_node->next_free_position += i;	return SUCCESS;}/*// NAME:	DeleteNodeKeyGroup//// DESCRIPTION:	Deletes the current active key by moving down the contents//		of upper end of the node past the current key to the //		current position.//// RETURN:	SUCCESS or FAIL//*/static int  DeleteNodeKeyGroup(BTREE * btree /* pointer to tree descriptor */){	int len,i;	char * cp;	Trace("DeleteNodeKeyGroup(%x)\n", (unsigned)btree);	if(btree->key_position > btree->active_node->total_node_keys){		/* cant delete at node eof*/		Debug("Invalid delete position\n");		return FAIL;	}	i = KeyGroupSize(btree /* pointer to tree descriptor */,btree->active_key);	len = ( ((char *)btree->active_node + btree->block_size ) - ( (char *)btree->active_key + i ) );	cp = (char *)btree->active_key;	mv_mem(cp + i, cp, len ); 	--btree->active_node->total_node_keys;	btree->active_node->next_free_position -= i;	(btree->hierarchy_list+btree->vector)->state = DIRTY;	return SUCCESS;}/*DeleteNodeKeyGroup()*//*// NAME:	Combine//// DESCRIPTION: 	This function attempts to combine sibling nodes following a//		key deletion.  Attempt is first made with the right node, //		and if that fails, with the left node.  If it results in the//		parent root being emptied, a new root node is created.//		Combine must be called immediately before a return //		and after all other processing on the hierarchy is completed.//// RETURN:	SUCCESS or FAIL//*/	static int Combine(BTREE * btree /* pointer to tree descriptor */){	long combine_id;	int combine_key_count;	int combine_data_size;	int combine_key_posn;	long sibling_id;	int sibling_key_count;	int sibling_data_size;	int sibling_key_posn;	int sibling_key_size;	long parent_id;	int parent_key_count;	int parent_data_size;	int parent_key_posn;	int parent_key_size;	int parent_pass_through_space;	int status, i;	int on_right, parent_is_root;	struct Node * spare_node;/* HERE - put the node on the statk??*/	struct KeyGroup * spare_key;	struct KeyGroup parent_key;	int root_exhausted;	long hold_left;	Trace("Combine(%x)\n", (unsigned)btree);	on_right = 0; 	combine_id = sibling_id = 0L; 	combine_key_count = parent_key_size = sibling_key_count = 0; 	root_exhausted = 0; 	/* save our current id */	combine_id = (btree->hierarchy_list+btree->vector)->block_id; 	if(Parent(btree)==NULL) { 		Debug("Couldnt locate parent\n"); 		return FAIL; 	}	/* Mark the parent as being root node*/	if(btree->vector == 0){		parent_is_root = 1;	}else{		parent_is_root = 0;	}	/* find the right side*/	status = SUCCESS;	while(btree->left != combine_id){		if(btree->active_key->right_node == combine_id)			on_right = 1; 		if( (status=IncrementPosition(btree)) != SUCCESS ){			if(on_right){				break;			} 			Debug("Failed to increment\n"); 			return FAIL; 		}		on_right = 0;	} 	if(on_right){		/* This is the condition where we are */		/* dealing with the far right node in a tree*/		Rewind(btree);		while(btree->active_key->right_node != combine_id){ 			if( (status=IncrementPosition(btree)) != SUCCESS ){				Debug("Failed to increment\n");				return FAIL;			}		}		combine_id = btree->left;		/* we have now swapped positions and are working with */		/* a separate set of nodes*/	}	/* this would be the parent key*/	mv_mem((char *)btree->active_key, (char *)&parent_key, 		KeyGroupSize(btree,btree->active_key));	parent_key_size = KeyGroupSize(btree,btree->active_key);	sibling_id = btree->active_key->right_node;	if( (btree->vector == 0) && (btree->active_node->total_node_keys == 1))		root_exhausted = 1;	/* --- we have our left and right sides*/	/* get left side data*/	if( LoadHierarchyNode( btree,combine_id ) == FAIL){ 		Debug("Cant load node\n");		return FAIL;	}	/* begin building the spare node*/	spare_node = (struct Node *)malloc(sizeof(struct Node) );/*fprintf(stderr, "%ld\n", (long)spare_node);*/	if(spare_node == NULL){		Debug("Insufficient available memory\n");	}	mv_mem( (char *)btree->active_node, (char *)spare_node, sizeof(struct Node) );	/* collect information*/	combine_key_count = btree->active_node->total_node_keys;	combine_key_posn =  btree->active_node->next_free_position;	combine_data_size = btree->active_node->next_free_position - FirstKeyOffset;	if(Parent(btree)==NULL){		Debug("Couldnt locate parent\n");		return FAIL;	}	parent_key_count = btree->active_node->total_node_keys;	parent_key_posn =  btree->active_node->next_free_position;	parent_data_size = btree->active_node->next_free_position - FirstKeyOffset;	parent_id = (btree->hierarchy_list+btree->vector)->block_id; 	parent_pass_through_space = KeySpace - parent_data_size + 		parent_key_size;	/* get right side data*/	if( LoadHierarchyNode( btree,sibling_id ) == FAIL){ 		Debug("Cant load node\n");		free((void*)spare_node);		return FAIL;	}	sibling_key_count = btree->active_node->total_node_keys;	sibling_key_posn =  btree->active_node->next_free_position;	sibling_data_size = btree->active_node->next_free_position - FirstKeyOffset;	sibling_key_size = KeyGroupSize(btree,btree->active_key);	parent_key.right_node = btree->left;	/* have we been wasting our time*/	if(		/* it is too big to combine*/	((combine_data_size+parent_key_size+sibling_data_size) > KeySpace ) ||		/* or, it is a variable length node and there wouldn't be */		/* space in the node if combined, to fit in an extra key*/	( (btree->type_of_key == VAR_LNG_KEY) && 	  ((combine_data_size+parent_key_size+sibling_data_size) > 		(( KeySpace / 5 ) * 4)))	)		{		/* then lets shift left*/		if (				/* if we have keys to shift*/		   (    sibling_key_count > 2) &&			/* and it would balance*/		   (	sibling_key_count > combine_key_count ) &&			/* and at least 1/5 th the available space is there*/			/* to accept a shifted key*/		   (    combine_data_size  < (( KeySpace / 5 ) * 4 )) &&			/* and if variable length keys, the sibling*/			/* key can fit into the parent*/		   ( ! ( (btree->type_of_key == VAR_LNG_KEY ) &&		    (  (sibling_key_size+1) > parent_pass_through_space ))) 		)		{			/* steal - shift some of the sibling to the*/			/* combine node*/			/* - we have the parent key, and are at the */			/* sibling.  We need the first sibling key in */			/* the parent, and the parent key in the combine*/			free((void *)spare_node);			Rewind(btree);			spare_key = (struct KeyGroup *)				malloc(sizeof(struct KeyGroup));			if(spare_key == NULL){				Debug("Insufficient available memory\n");			}

⌨️ 快捷键说明

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