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

📄 ridxio.c

📁 T-kernel 的extension源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	err = fmpCheckDiskError(ri->ofcb, fsinfo);	if ( err < E_OK ) {		goto err_ret;	}	blktp = 0;	while ( total < end ) {		/* Obtain the location and size of the data block from the record index. */		err = fmpGetDataBlkAdr(ri, lblk);		if ( err < E_OK ) {			goto err_ret;		}		blktp = total;		total += (UW)(lblk->cnt * fsinfo->sblk);	}	return (WER)(end - blktp);err_ret:	ri->err = err;	DEBUG_PRINT(("fmpFindLastDataBlkAdr err = %d\n", err));	return err;}/* ------------------------------------------------------------------------ *//* * Down the range between top and end by one level. * The indirect index at the location of end is abandoned. * The indirect index at the location of top is cleared to 0. * Return the record count included in the moved indirect index. */LOCAL W shiftDownIIdx( DfIndirectIndex *base, W top, W end, FsInfo *fsinfo ){	W	i;	W	n = 0;	for ( i = end - 1; i >= top; --i ) {		base[i + 1] = base[i];		n += (W)fmpConvEndianW(base[i].nrec, fsinfo);	}	memset(&base[top], 0, (size_t)sizeof(DfIndirectIndex));	return n;}/* * Up the range between top and end by one level. * The indirect index at the location of top is abandoned. * The indirect index at the location of end is cleared to 0. * Return the record count included in the moved indirect index. */LOCAL W shiftUpIIdx( DfIndirectIndex *base, W top, W end, FsInfo *fsinfo ){	W	i;	W	n = 0;	for ( i = top + 1; i <= end; ++i ) {		base[i - 1] = base[i];		n += (W)fmpConvEndianW(base[i].nrec, fsinfo);	}	memset(&base[end], 0, (size_t)sizeof(DfIndirectIndex));	return n;}/* * Down the range between top and end by one level. * The record index at the location of end is abandoned. * The record index at the location of top is cleared to 0. * Return the numbers of normal indexes and link indexes * in the moved record index. */LOCAL W shiftDownRIdx( DfRecordIndex *base, W top, W end ){	W	i;	W	n = 0;	for ( i = end - 1; i >= top; --i ) {		base[i + 1] = base[i];		if ( (base[i].type[0] == 0) && (base[i].type[1] != 0) ) {			n++;		}	}	memset(&base[top], 0, (size_t)sizeof(DfRecordIndex));	return n;}/* * Up the range between top and end by one level. * The record index at the location of top is abandoned. * The record index at the location of end is cleared to 0. * Return the numbers of normal indexes and link indexes * in the moved record index. */LOCAL W shiftUpRIdx( DfRecordIndex *base, W top, W end ){	W	i;	W	n = 0;	for ( i = top + 1; i <= end; ++i ) {		base[i - 1] = base[i];		if ( (base[i].type[0] == 0) && (base[i].type[1] != 0) ) {			n++;		}	}	memset(&base[end], 0, (size_t)sizeof(DfRecordIndex));	return n;}/* * Obtain a free entry from the indirect index block. *	Find a free entry in the indirect index block of index level lv that includes *	the indirect index at the location of *dadr, and locate it just after *dadr. *	If needed, move the entry in the indirect index block to reserve a free entry. *	If the location of *dadr is moved, *dadr is updated to indicate the location *	after the movement. *	Return the record count included in the moved entry to *nrec. *	When the entry before *dadr is moved, *nrec < 0. *	When the entry after *dadr is moved, *nrec >= 0. *	Return the address of the obtained free entry being mapped to the return value. *	When *mid == E_LIMIT, it is shown that no free entry was found. *	When no free entry was found, return the record count after *dadr to *nrec. * */LOCAL DfIndirectIndex* getFreeIIdx( DskAdr *dadr, W lv,					OFCB *ofcb, ID_ERR *mid, W *nrec ){	FsInfo		*fsinfo = ofcb->fsinfo;	LogAdr		ladr;	DfIndirectIndex	*baseIIdx;	W		cur, top, end, i;	W		arec;	ER		err;	ladr = fmpDAdrToLAdr(*dadr, fsinfo);	cur = (W)(ladr.offset  / sizeof(DfIndirectIndex));	top = (W)TopIIdx(lv, ofcb);	end = (W)(fsinfo->sblk / sizeof(DfIndirectIndex));	/* Map the indirect index block. */	baseIIdx = fmpMapLogBlk(ladr.blk, ofcb, mid, fsinfo);	if ( baseIIdx == NULL ) {		err = (ER)*mid;		goto err_ret;	}	arec = 0;  /* Record count after *dadr */	/* Find a free indirect index from after cur. */	for ( i = cur + 1; i < end; ++i ) {		if ( baseIIdx[i].blk == 0U ) {			/* Move index to make a space just after cur. */			*nrec = shiftDownIIdx(baseIIdx, cur + 1, i, fsinfo);			return &baseIIdx[cur + 1];		}		arec += (W)fmpConvEndianW(baseIIdx[i].nrec, fsinfo);	}	/* Find a free indirect index from before cur. */	for ( i = cur - 1; i >= top; --i ) {		if ( baseIIdx[i].blk == 0U ) {			/* Move index to make a space just after cur. */			*nrec = - shiftUpIIdx(baseIIdx, i, cur, fsinfo);			/* Since the location of cur was moved, move *dadr too */			dadr->offset = (VP)((VB*)dadr->offset - sizeof(DfIndirectIndex));			return &baseIIdx[cur];		}	}	fmpUnmapDisk(*mid, MD_RDONLY);	/* No space found. */	*nrec = arec;	*mid = E_LIMIT;	return NULL;err_ret:	DEBUG_PRINT(("getFreeIIdx err = %d\n", err));	*mid = err;	return NULL;}/* * Extend the index level by one level. */LOCAL ER expandIndexLevel( RIdx *ri ){	UW			oldblk, newblk;	DfFileHeaderBlock	*old, *new;	DfIndirectIndex		*iidx;	DfFileID		*fidt, f;	W			size;	ID			oldmid, newmid, mid;	OFCB			*ofcb = ri->ofcb;	FsInfo			*fsinfo = ofcb->fsinfo;	ER			err;	if ( ofcb->idxlv >= MaxIndexLevel ) {		/* Unable to extend any more. */		err = E_LIMIT;		goto err_ret1;	}	/* Map the current file header. */	oldblk = fmpDAdrToLBlk(ofcb->fhead, fsinfo);	old = fmpMapLogBlk(oldblk, ofcb, &oldmid, fsinfo);	if ( old == NULL ) {		err = (ER)oldmid;		goto err_ret1;	}	/* Reserve new block. */	err = fmpAllocateOneBlock(oldblk, ofcb, fsinfo);	if ( err < E_OK ) {		goto err_ret2;	}	newblk = (UW)err;	/* Use the new block as new file header. */	new = fmpMapAndClearLogBlk(newblk, ofcb, &newmid, fsinfo);	if ( new == NULL ) {		err = (ER)newmid;		goto err_ret2;	}	/* Move the file header to the new block.	  Move the file header excluding the record index/indirect index,	   and the fragment table to the new block. */	size = (W)ofcb->ridxofs;	memcpy(new, old, (size_t)size);	memset(old, 0, (size_t)size); /* The old block is cleared to 0 as an unused index. */	/* Register the index block of the new block in the indirect index	  as old header block. */	iidx = (DfIndirectIndex*)((VB*)new + ofcb->ridxofs);	iidx->blk  = fmpConvEndianW(oldblk, fsinfo);	iidx->nrec = fmpConvEndianW((UW)ofcb->nrec, fsinfo);	/* Update the index level. */	ofcb->idxlv++;	new->head.idxlv = (H)fmpConvEndianH((UH)ofcb->idxlv, fsinfo);	fmpUnmapDisk(newmid, MD_WRITE);	fmpUnmapDisk(oldmid, MD_WRITE);	/* Register the new header block in the file ID table. */	fidt = fmpMapFileID(ofcb->fid, &mid, fsinfo);	if ( fidt == NULL ) {		err = (ER)mid;		goto err_ret1;	}	f = fmpConvEndianFileID(*fidt, fsinfo);	f.s.blkadr = newblk;	*fidt = fmpConvEndianFileID(f, fsinfo);	ofcb->fhead = fmpLBlkToDAdr(newblk, fsinfo);	fmpUnmapDisk(mid, MD_WRITE);	err = fmpCheckDiskError(ofcb, fsinfo);	if ( err < E_OK ) {		goto err_ret1;	}	/* Extend the index level of RCB. */	fmpExpandIndexLevelRCB(ofcb);	/* Extend the index level of ri. */	fmpExpandIdxAdr(&ri->adr, FHeadIdxDAdr(ofcb));	return E_OK;err_ret2:	fmpUnmapDisk(oldmid, MD_RDONLY);err_ret1:	DEBUG_PRINT(("expandIndexLevel err = %d\n", err));	return err;}/* * Adjust the indirect index. *	When moving the record index of nrec from the record index block of *curidx *	to the record index block of *nxtidx, adjust the record count included *	in indirect indexes of *curidx and *nxtidx. */LOCAL ER tuneIIdx( IdxAdr *curidx, IdxAdr *nxtidx, W lv, W nrec, OFCB *ofcb ){	FsInfo		*fsinfo = ofcb->fsinfo;	DfIndirectIndex	*cur, *nxt;	ID		curmid, nxtmid;	UW		n;	W		i;	ER		err;	for ( i = 0; i < lv; ++i ) {		if ( (curidx->iidx[i].offset == nxtidx->iidx[i].offset)		  && (curidx->iidx[i].lblk   == nxtidx->iidx[i].lblk) ) {			continue;		}		/* Map the indirect indexe of each. */		cur = fmpMapDskAdr(curidx->iidx[i], sizeof(DfIndirectIndex),						ofcb, &curmid, fsinfo);		if ( cur == NULL ) {			err = (ER)curmid;			goto err_ret1;		}		nxt = fmpMapDskAdr(nxtidx->iidx[i], sizeof(DfIndirectIndex),						ofcb, &nxtmid, fsinfo);		if ( nxt == NULL ) {			err = (ER)nxtmid;			goto err_ret2;		}		/* Adjust the record count */		n = fmpConvEndianW(cur->nrec, fsinfo) - (UW)nrec;		cur->nrec = fmpConvEndianW(n, fsinfo);		n = fmpConvEndianW(nxt->nrec, fsinfo) + (UW)nrec;		nxt->nrec = fmpConvEndianW(n, fsinfo);		fmpUnmapDisk(curmid, MD_WRITE);		fmpUnmapDisk(nxtmid, MD_WRITE);	}	err = fmpCheckDiskError(ofcb, fsinfo);	if ( err < E_OK ) {		goto err_ret1;	}	return E_OK;err_ret2:	fmpUnmapDisk(curmid, MD_RDONLY);err_ret1:	DEBUG_PRINT(("tuneIIdx err = %d\n", err));	return err;}/* * Divide the indirect index. *	Divide the indirect index that includes the current location ri->adr.iidx[lv] *	at the current location, and move to the new block blk. *	*next is updated so that it indicates the next entry to the current *	location ri->adr.iidx[lv]. Map the indirect index that the updated *next indicates, *	and return the address. *	When lv == ofcb->idxlv, the record index is added and the indirect index *	is not divided. Map the whole record index, *	 and return the address. *	Return the number of records that moved to *nrec. *	The new block is used after it is cleared to 0. */LOCAL DfIndirectIndex* divideIIdxBlock( RIdx *ri, IdxAdr *next, W lv, UW blk,							W *nrec, ID_ERR *mid ){	DfIndirectIndex	*nxtbase, *curbase, *nxt, *cur, *end;	LogAdr		curblk;	ID		curmid;	W		nr;	OFCB		*ofcb = ri->ofcb;	FsInfo		*fsinfo = ofcb->fsinfo;	ER		err;	/* Map the new block (0 clear) */	nxtbase = fmpMapAndClearLogBlk(blk, ofcb, mid, fsinfo);	if ( nxtbase == NULL ) {		err = (ER)*mid;		goto err_ret1;	}	/* When the record index is added, the division is not made. */	if ( lv == ofcb->idxlv ) {		*nrec = 0;		return nxtbase;	}	/* Map the indirect index block at the current location. */	curblk = fmpDAdrToLAdr(ri->adr.iidx[lv], fsinfo);	curbase = fmpMapLogBlk(curblk.blk, ofcb, &curmid, fsinfo);	if ( curbase == NULL ) {		err = (ER)curmid;		goto err_ret2;	}	/* Divide Move */	cur = (DfIndirectIndex*)((VB*)curbase + curblk.offset);	end = (DfIndirectIndex*)((VB*)curbase + fsinfo->sblk);	nxt = nxtbase;	nr = 0;	while ( ++cur < end ) {		nr += (W)fmpConvEndianW(cur->nrec, fsinfo);		*(nxt++) = *cur;		memset(cur, 0, (size_t)sizeof(DfIndirectIndex)); /* The old block is cleared to 0. */	}	/* Obtain the location of the indirect index entry next to the current location. */	nxt = (DfIndirectIndex*)((VB*)curbase + curblk.offset) + 1;	if ( nxt < end ) {		fmpUnmapDisk(*mid, MD_WRITE);		*mid = curmid;		*next = ri->adr;		next->iidx[lv].offset = (VP)((DfIndirectIndex*)next->iidx[lv].offset + 1);	} else {		fmpUnmapDisk(curmid, MD_WRITE);		nxt = nxtbase;		next->iidx[lv] = fmpLBlkToDAdr(blk, fsinfo);	}	err = fmpCheckDiskError(ofcb, fsinfo);	if ( err < E_OK ) {		goto err_ret2;	}	/* Adjust the indirect index. */	err = tuneIIdx(&ri->adr, next, lv, nr, ofcb);	if ( err < E_OK ) {		goto err_ret2;	}	*nrec = nr;	return nxt;err_ret2:	fmpUnmapDisk(*mid, MD_WRITE);err_ret1:	DEBUG_PRINT(("divideIIdxBlock err = %d\n", err));	*mid = err;	return NULL;}/* * Add the record index block. *	Add new record index block just after the index block that contains the current *	location of ri. The added index block is cleared to 0. *	The current location of ri does not change. *	rcb must indicate the record at current location of ri. *	Set arec to the record count after the current location included *	in the index block including the current location of ri. *	Return the number of records moved between the index blocks to the return value. */LOCAL WER appendRIdxBlock( RIdx *ri, RCB *rcb, W arec ){	DfIndirectIndex	*iidx;	W		blk;	W		i, j;	W		nrec, ar, n;	ID		mid;	IdxAdr		next;	OFCB		*ofcb = ri->ofcb;	FsInfo		*fsinfo = ofcb->fsinfo;	ER		err;	ar = arec;	for ( i = ofcb->idxlv - 1; i >= 0; --i ) {		/* Obtain a free entry of the indirect index. */		iidx = getFreeIIdx(&ri->adr.iidx[i], i, ofcb, &mid, &nrec);		if ( iidx == NULL ) {			err = (ER)mid;			if ( err != E_LIMIT ) {				goto err_ret1;			}			/* Since no free entry is found, move to the indirect index of one level higher. */			ar += nrec;			continue;		}		/* Reflect the movement made to create the free entry to RCB. */		if ( nrec >= 0 ) {			fmpShiftIdxAdrRCB(rcb, i, ar + 1, ar + nrec, 1);		} else {			fmpShiftIdxAdrRCB(rcb, i, ar + nrec + 1, ar, TSD_SIA_RC5_M1);		}		/* Add the index block. */		blk = (W)fmpDAdrToLBlk(ri->adr.iidx[i], fsinfo);		next = ri->adr;		next.iidx[i].offset = (VP)((DfIndirectIndex*)next.iidx[i].offset + 1);		nrec = 0;		for ( j = i + 1; j <= ofcb->idxlv; ++j ) {			/* Obtain new block. */			blk = fmpAllocateOneBlock((UW)blk, ofcb, fsinfo);			if ( blk < E_OK ) {				err = (ER)blk;				goto err_ret2;			}			/* Connect to the indirect index. */			iidx->blk = fmpConvEndianW((UW)blk, fsinfo);			fmpUnmapDisk(mid, MD_WRITE);			/* Divide the index block at the current location,			   and move it to new block. */			iidx = divideIIdxBlock(ri, &next, j, (UW)blk, &n, &mid);			if ( iidx == NULL ) {				err = (ER)mid;				goto err_ret1;			}			nrec += n;		}		fmpUnmapDisk(mid, MD_WRITE);		err = fmpCheckDiskError(ofcb, fsinfo);		if ( err < E_OK ) {			goto err_ret1;		}		return nrec;	}	/* Extend the index level */	err = expandIndexLevel(ri);	if ( err < E_OK ) {		goto err_ret1;	}	/* Add the index block. */	err = appendRIdxBlock(ri, rcb, arec);	if ( err < E_OK ) {		goto err_ret1;	}	return err;err_ret2:	fmpUnmapDisk(mid, MD_WRITE);err_ret1:	DEBUG_PRINT(("appendRIdxBlock err = %d\n", err));	return err;}/* * Divide the record index block. *	Divide the current record index block of ri into the part before *	the div th record index and the part after div th record index, *	and move the later to the next record index block. *	The next record index block must be free. *	The current location of ri does not change. *	Return the number of records moved between blocks to the return value. */LOCAL WER divideRIdxBlock( RIdx *ri, W div ){	UW		nxtblk;	IdxAdr		nxtidx, curidx;	DfRecordIndex	*nxt, *cur, *end;	W		nrec;	OFCB		*ofcb = ri->ofcb;	FsInfo		*fsinfo = ofcb->fsinfo;	ID		nxtmid;	ER		err;	nxtidx = curidx = fmpGetIdxAdr(ri);	/* Next record index block */	err = getNextRIdxBlk(&nxtidx, ofcb);	if ( err < E_OK ) {		goto err_ret;	}	nxtblk = fmpDAdrToLBlk(nxtidx.ridx, fsinfo);	/* Map the next record index block */	nxt = fmpMapLogBlk(nxtblk, ofcb, &nxtmid, fsinfo);	if ( nxt == NULL ) {		err = (ER)nxtmid;		goto err_ret;	}	/* Divide Move */	cur = &ri->mapbase[div];	end = (DfRecordIndex*)((VB*)ri->mapbase + fsinfo->sblk);

⌨️ 快捷键说明

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