📄 ridxio.c
字号:
/* *---------------------------------------------------------------------- * 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 + -