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

📄 ridxio.c

📁 T-kernel 的extension源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *---------------------------------------------------------------------- *    T-Kernel / Standard Extension * *    Copyright (C) 2006 by Ken Sakamura. All rights reserved. *    T-Kernel / Standard Extension is distributed  *      under the T-License for T-Kernel / Standard Extension. *---------------------------------------------------------------------- * *    Version:   1.00.00 *    Released by T-Engine Forum(http://www.t-engine.org) at 2006/8/11. * *---------------------------------------------------------------------- *//* *	ridxio.c (file) * *	File management *	Input/Output of the record index */#include "fsinfo.h"#include "diskio.h"#include "dskalloc.h"#define TSD_FDB_VAL_4		4#define TSD_FSI_POS_0		0#define TSD_FSI_POS_1		1#define TSD_FSI_POS_2		2#define TSD_FSI_POS_3		3#define TSD_FSI_POS_4		4#define TSD_SIA_RC5_M1		(-1)#define TSD_SIA_RC2_M1		(-1)#define TSD_FDR_VAL_M1		(-1)#define TSD_RID_CP_5		5#define TSD_RID_CP_3		3#define TSD_FSI_ALW_0X80	(UB)0x80#define TSD_FSI_RTY_0X80	(UB)0x80LOCAL DfIndirectIndex* findAndMapIIdx( DskAdr *dadr, OFCB *ofcb, ID_ERR *mid );LOCAL DfIndirectIndex* RfindAndMapIIdx( DskAdr *dadr, OFCB *ofcb, ID_ERR *mid );LOCAL ER getFirstRIdx( IdxAdr *idxadr, OFCB *ofcb );LOCAL ER getLastRIdx( IdxAdr *idxadr, OFCB *ofcb );LOCAL ER getNextRIdxBlk( IdxAdr *idxadr, OFCB *ofcb );LOCAL ER gotoNextRIdxBlk( RIdx *ri );LOCAL W shiftDownIIdx( DfIndirectIndex *base, W top, W end, FsInfo *fsinfo );LOCAL W shiftUpIIdx( DfIndirectIndex *base, W top, W end, FsInfo *fsinfo );LOCAL W shiftDownRIdx( DfRecordIndex *base, W top, W end );LOCAL W shiftUpRIdx( DfRecordIndex *base, W top, W end );LOCAL DfIndirectIndex* getFreeIIdx( DskAdr *dadr, W lv, OFCB *ofcb, ID_ERR *mid, W *nrec );LOCAL ER expandIndexLevel( RIdx *ri );LOCAL ER tuneIIdx( IdxAdr *curidx, IdxAdr *nxtidx, W lv, W nrec, OFCB *ofcb );LOCAL DfIndirectIndex* divideIIdxBlock( RIdx *ri, IdxAdr *next, W lv, UW blk, W *nrec, ID_ERR *mid );LOCAL WER appendRIdxBlock( RIdx *ri, RCB *rcb, W arec );LOCAL WER divideRIdxBlock( RIdx *ri, W div );LOCAL ER appendRIdx( RIdx *ri, RCB *rcb );LOCAL ER insertRIdx( RIdx *ri, RCB *rcb );LOCAL ER changeRecordCountIIdx( IdxAdr *idxadr, W diff, OFCB *ofcb );LOCAL ER deleteRIdxBlock( RIdx *ri );/* * Find an indirect index being used from after *dadr in one logical block, *  and map it to return the address. Return the disk address to *dadr. */LOCAL DfIndirectIndex* findAndMapIIdx( DskAdr *dadr, OFCB *ofcb, ID_ERR *mid ){	FsInfo		*fsinfo = ofcb->fsinfo;	LogAdr		ladr;	DfIndirectIndex	*iidx;	VB		*blk, *end;	ladr = fmpDAdrToLAdr(*dadr, fsinfo);	blk = fmpMapLogBlk(ladr.blk, ofcb, mid, fsinfo);	iidx = (DfIndirectIndex*)(blk + ladr.offset);	end = blk + fsinfo->sblk;	while ( (VB*)iidx < end ) {		if ( iidx->blk != 0U ) {			/* Found */			ladr.offset = (UW)((VB*)iidx - blk);			*dadr = fmpLAdrToDAdr(ladr, fsinfo);			return iidx;		}		iidx++;	}	/* Not found */	fmpUnmapDisk(*mid, MD_RDONLY);	*mid = fmpCheckDiskError(ofcb, fsinfo);	if ( *mid == E_OK ) {		*mid = E_ILFMT; /* Abnormal disk format */	}	return NULL;}/* * Find an indirect index being used from after *dadr in one logical block in inverse order * (From the end of block toward the start), and map it to return the address. * Return the disk address to *dadr. */LOCAL DfIndirectIndex* RfindAndMapIIdx( DskAdr *dadr, OFCB *ofcb, ID_ERR *mid ){	FsInfo		*fsinfo = ofcb->fsinfo;	LogAdr		ladr;	DfIndirectIndex	*iidx;	W		top, end, i;	ladr = fmpDAdrToLAdr(*dadr, fsinfo);	iidx = fmpMapLogBlk(ladr.blk, ofcb, mid, fsinfo);	top = (W)(ladr.offset  / sizeof(DfIndirectIndex));	end = (W)(fsinfo->sblk / sizeof(DfIndirectIndex));	for ( i = end - 1; i >= top; --i ) {		if ( iidx[i].blk != 0U ) {			/* Found */			ladr.offset = (UW)((VB*)&iidx[i] - (VB*)iidx);			*dadr = fmpLAdrToDAdr(ladr, fsinfo);			return &iidx[i];		}	}	/* Not found */	fmpUnmapDisk(*mid, MD_RDONLY);	*mid = fmpCheckDiskError(ofcb, fsinfo);	if ( *mid == E_OK ) {		*mid = E_ILFMT; /* Abnormal disk format */	}	return NULL;}/* * Obtain the first record index. */LOCAL ER getFirstRIdx( IdxAdr *idxadr, OFCB *ofcb ){	FsInfo		*fsinfo = ofcb->fsinfo;	DskAdr		idx;	DfIndirectIndex	*iidx;	W		i;	ID		mid;	ER		err;	idx = FHeadIdxDAdr(ofcb);	/* Trace the indirect index. */	for ( i = 0; i < ofcb->idxlv; ++i ) {		/* Find an indirect index. */		iidx = findAndMapIIdx(&idx, ofcb, &mid);		if ( iidx == NULL ) {			return (ER)mid;		}		idxadr->iidx[i] = idx;		/* Obtain the next index address from the indirect index. */		idx = fmpLBlkToDAdr(fmpConvEndianW(iidx->blk, fsinfo), fsinfo);		fmpUnmapDisk(mid, MD_RDONLY);		err = fmpCheckDiskError(ofcb, fsinfo);		if ( err < E_OK ) {			return err;		}	}	/* Record index */	idxadr->ridx = idx;	return E_OK;}/* * Obtain the end record index. */LOCAL ER getLastRIdx( IdxAdr *idxadr, OFCB *ofcb ){	FsInfo		*fsinfo = ofcb->fsinfo;	DskAdr		idx;	LogAdr		ladr;	DfIndirectIndex	*iidx;	W		i;	ID		mid;	ER		err;	idx = FHeadIdxDAdr(ofcb);	/* Trace the indirect index */	for ( i = 0; i < ofcb->idxlv; ++i ) {		/* Find the indirect index. */		iidx = RfindAndMapIIdx(&idx, ofcb, &mid);		if ( iidx == NULL ) {			return (ER)mid;		}		idxadr->iidx[i] = idx;		/* Obtain the next index address from the indirect index. */		idx = fmpLBlkToDAdr(fmpConvEndianW(iidx->blk, fsinfo), fsinfo);		fmpUnmapDisk(mid, MD_RDONLY);		err = fmpCheckDiskError(ofcb, fsinfo);		if ( err < E_OK ) {			return err;		}	}	/* Record index */	ladr.blk = fmpDAdrToLBlk(idx, fsinfo);	ladr.offset = fsinfo->sblk - sizeof(DfRecordIndex);	idxadr->ridx = fmpLAdrToDAdr(ladr, fsinfo);	return E_OK;}/* * Obtain the logical block that includes the next record index. */LOCAL ER getNextRIdxBlk( IdxAdr *idxadr, OFCB *ofcb ){	FsInfo		*fsinfo = ofcb->fsinfo;	DskAdr		idx;	DfIndirectIndex	*iidx;	W		i, j;	ID		mid;	ER		err;	for ( i = ofcb->idxlv - 1; i >= 0; --i ) {		/* Advance the location of the indirect index by 1. */		idx = idxadr->iidx[i];		idx.offset = (VP)((VB*)idx.offset + sizeof(DfIndirectIndex));		if ( ((UW)idx.offset % (UW)fsinfo->sblk) == 0U ) {			/* The end of the logical block */			continue;		}		/* Find an indirect index. */		iidx = findAndMapIIdx(&idx, ofcb, &mid);		if ( iidx == NULL ) {			if ( (ER)mid != E_ILFMT ) {				return (ER)mid;			}			/* The end of the logical block */			continue;		}		idxadr->iidx[i] = idx;		/* Obtain the next index address from the indirect index. */		idx = fmpLBlkToDAdr(fmpConvEndianW(iidx->blk, fsinfo), fsinfo);		fmpUnmapDisk(mid, MD_RDONLY);		err = fmpCheckDiskError(ofcb, fsinfo);		if ( err < E_OK ) {			return err;		}		/* Trace the indirect index */		for ( j = i + 1; j < ofcb->idxlv; ++j ) {			/* Find an indirect index. */			iidx = findAndMapIIdx(&idx, ofcb, &mid);			if ( iidx == NULL ) {				return (ER)mid;			}			idxadr->iidx[j] = idx;			/* Obtain the next index address. */			idx = fmpLBlkToDAdr(				fmpConvEndianW(iidx->blk, fsinfo), fsinfo);			fmpUnmapDisk(mid, MD_RDONLY);			err = fmpCheckDiskError(ofcb, fsinfo);			if ( err < E_OK ) {				return err;			}		}		/* Record index. */		idxadr->ridx = idx;		return E_OK;	}	return E_ILFMT; /* Abnormal disk format */}/* * Move to the next record index block. */LOCAL ER gotoNextRIdxBlk( RIdx *ri ){	VP		mp;	OFCB		*ofcb = ri->ofcb;	FsInfo		*fsinfo = ofcb->fsinfo;	ER		err;	if ( ri->mid > 0 ) {		/* Unmap the block now being mapped. */		fmpUnmapDisk(ri->mid, ri->mflag);		ri->mid = 0;		ri->mflag = MD_RDONLY;	}	/* Move the logical block. */	err = getNextRIdxBlk(&ri->adr, ofcb);	if ( err < E_OK ) {		goto err_ret;	}	ri->lblk = fmpDAdrToLBlk(ri->adr.ridx, fsinfo);	/* Map the moved logical block. */	mp =fmpMapLogBlk(ri->lblk, ofcb, &ri->mid, fsinfo);	if ( mp == NULL ) {		err = (ER)ri->mid;		goto err_ret;	}	ri->mapadr = ri->mapbase = (DfRecordIndex*)mp;	return E_OK;err_ret:	ri->mapadr = ri->mapbase = NULL;	DEBUG_PRINT(("gotoNextRIdxBlk err = %d\n", err));	return err;}/* * Open (initialization) */EXPORT ER fmpOpenRIdx( RIdx *ri, IdxAdr *idxadr, OFCB *ofcb ){	FsInfo	*fsinfo = ofcb->fsinfo;	LogAdr	ladr;	ER	err;	memset(ri, 0, (size_t)sizeof(RIdx));	ri->ofcb = ofcb;	if ( idxadr == FIRST_RIdx ) {		/* From the record index at the start of file. */		err = getFirstRIdx(&ri->adr, ofcb);		if ( err < E_OK ) {			goto err_ret;		}	} else if ( idxadr == LAST_RIdx ) {		/* From the record index at the end of file. */		err = getLastRIdx(&ri->adr, ofcb);		if ( err < E_OK ) {			goto err_ret;		}	} else {		/* From the record index of idxadr. */		ri->adr = *idxadr;	}	/* Obtain the logical block. */	ladr = fmpDAdrToLAdr(ri->adr.ridx, fsinfo);	ri->lblk = ladr.blk;	/* Map the logical block. */	ri->mapbase = fmpMapLogBlk(ri->lblk, ofcb, &ri->mid, fsinfo);	if ( ri->mapbase == NULL ) {		err = (ER)ri->mid;		goto err_ret;	}	ri->mflag = MD_RDONLY;	ri->mapadr = (DfRecordIndex*)((VB*)ri->mapbase + ladr.offset);	ri->cp = TSD_RID_CP_5;	return E_OK;err_ret:	ri->err = err;	DEBUG_PRINT(("fmpOpenRIdx err = %d\n", err));	return err;}/* * Close (Termination) */EXPORT ER fmpCloseRIdx( RIdx *ri ){	ER	err;	if ( ri->mid > 0 ) {		/* Unmap the block now being mapped. */		fmpUnmapDisk(ri->mid, ri->mflag);	}	err = fmpCheckDiskError(ri->ofcb, ri->ofcb->fsinfo);	if ( err < E_OK ) {		ri->err = err;	}	return ri->err;}/* * Move the location of the record index. */EXPORT ER fmpSeekRIdx( RIdx *ri, IdxAdr *idxadr ){	FsInfo	*fsinfo = ri->ofcb->fsinfo;	LogAdr	ladr;	ER	err;	/* Logical block at the destination */	ladr = fmpDAdrToLAdr(idxadr->ridx, fsinfo);	if ( ladr.blk != ri->lblk ) {		/* Move the block. */		ri->lblk = ladr.blk;		if ( ri->mid > 0 ) {			/* Unmap the block now being mapped. */			fmpUnmapDisk(ri->mid, ri->mflag);			ri->mflag = MD_RDONLY;		}		/* Map the logical block at the destination. */		ri->mapbase =fmpMapLogBlk(ri->lblk,					ri->ofcb, &ri->mid, fsinfo);		if ( ri->mapbase == NULL ) {			err = (ER)ri->mid;			goto err_ret;		}	}	ri->adr = *idxadr;	ri->mapadr = (DfRecordIndex*)((VB*)ri->mapbase + ladr.offset);	ri->cp = TSD_RID_CP_5;	return E_OK;err_ret:	ri->err = err;	DEBUG_PRINT(("fmpSeekRIdx err = %d\n", err));	return err;}/* * Fetch one record index. */EXPORT DfRecordIndex* fmpGetRIdx( RIdx *ri ){	FsInfo		*fsinfo = ri->ofcb->fsinfo;	UW		lblk;	DfRecordIndex	*mapadr;	ER		err;	/* Logical block where the record index exists. */	lblk = fmpDAdrToLBlk(ri->adr.ridx, fsinfo);	if ( lblk != ri->lblk ) {		/* Move to the next record index. */		err = gotoNextRIdxBlk(ri);		if ( err < E_OK ) {			goto err_ret;		}	}	mapadr = ri->mapadr;	ri->cp = ( mapadr->type[0] == 0 )? TSD_RID_CP_3: 0;	/* Advance the location of the record index. */	ri->adr.ridx.offset = (VP)((VB*)ri->adr.ridx.offset + sizeof(DfRecordIndex));	ri->mapadr++;	err = fmpCheckDiskError(ri->ofcb, fsinfo);	if ( err < E_OK ) {		goto err_ret;	}	return mapadr;err_ret:	ri->err = err;	DEBUG_PRINT(("fmpGetRIdx err = %d\n", err));	return NULL;}/* * Fetch one record index corresponding to the record. *  (Normal index or Link index) */EXPORT DfRecordIndex* fmpGetRecordRIdx( RIdx *ri ){	DfRecordIndex	*ridx;	/* Skip unused index and connection index if any. */	do {		ridx = fmpGetRIdx(ri);		if ( ridx == NULL ) {			goto err_ret;		}	} while ( (ridx->type[0] != 0) || (ridx->type[1] == 0) );	return ridx;err_ret:	DEBUG_PRINT(("fmpGetRecordRIdx err = %d\n", ri->err));	return NULL;}/* * Fetch the data block address from the record index in order. *	It is assumed that the current record is a normal index or connection index. *	In the case of other index, a malfunction occurs. *	Return the logical block address to *lblk */EXPORT ER fmpGetDataBlkAdr( RIdx *ri, LogBlk *lblk ){	FsInfo		*fsinfo = ri->ofcb->fsinfo;	DfRecordIndex	*ridx;	ER		err;	if ( ri->cp > TSD_RID_CP_3 ) {		/* Move to the next record index */		ridx = fmpGetRIdx(ri);		if ( ridx == NULL ) {			goto err_ret;		}	} else {		/* Current record index */		ridx = ri->mapadr - 1;	}	/* Fetch the data block address. */	*lblk = fmpConvEndianLogBlk(ridx->c.blk[ri->cp], fsinfo);	/* Advance the location of data block read. */	ri->cp++;	err = fmpCheckDiskError(ri->ofcb, fsinfo);	if ( err < E_OK ) {		ri->err = err;		goto err_ret;	}	return E_OK;err_ret:	DEBUG_PRINT(("fmpGetDataBlkAdr err = %d\n", ri->err));	return ri->err;}/* * Find the data block address at the record end. *	The currant record index must be a normal index. *	Return the logical block address at the record end to *lblk. *	The record index corresponding to the record end becomes the current record index. *	Return the byte position of the data end to the return value as an offset in *lblk. */EXPORT WER fmpFindLastDataBlkAdr( RIdx *ri, LogBlk *lblk ){	FsInfo		*fsinfo = ri->ofcb->fsinfo;	DfRecordIndex	*ridx;	UW		blktp, total, end;	ER		err;	if ( ri->cp >= TSD_RID_CP_5 ) {		/* Just after RIdx open */		err = fmpGetDataBlkAdr(ri, lblk);		if ( err < E_OK ) {			goto err_ret;		}	}	ridx = ri->mapadr - 1;	*lblk = fmpConvEndianLogBlk(ridx->n.blk, fsinfo);	total = (UW)(lblk->cnt * fsinfo->sblk);	/* Byte position of the record end */	end = fmpConvEndianW(ridx->n.size, fsinfo)	    + fmpConvEndianH(ridx->n.offset, fsinfo);

⌨️ 快捷键说明

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