📄 ridxio.c
字号:
nrec = 0; while ( cur < end ) { if ( (cur->type[0] == 0) && (cur->type[1] != 0) ) { nrec++; } *(nxt++) = *cur; memset(cur, 0, (size_t)sizeof(DfRecordIndex)); /* The old block is cleared to 0. */ cur++; } fmpSetRIdxMapFlag(ri, MD_WRITE); fmpUnmapDisk(nxtmid, MD_WRITE); err = fmpCheckDiskError(ofcb, fsinfo); if ( err < E_OK ) { goto err_ret; } /* Adjust the indirect index. */ err = tuneIIdx(&curidx, &nxtidx, ofcb->idxlv, nrec, ofcb); if ( err < E_OK ) { goto err_ret; } return nrec;err_ret: DEBUG_PRINT(("divideRIdxBlock err = %d\n", err)); return err;}/* * Add the record index. * Add the new record index just after the current location of ri. * The added record index is cleared to 0 * The current location of ri does not change. */LOCAL ER appendRIdx( RIdx *ri, RCB *rcb ){ DfRecordIndex *ridx; W cur, top, end, i; W nrec, arec; ER err; cur = (ri->mapadr - ri->mapbase) - 1; top = (W)TopRIdx(ri->ofcb->idxlv, ri->ofcb); end = (W)(ri->ofcb->fsinfo->sblk / sizeof(DfRecordIndex)); arec = 0; /* The record count after the current record */ /* Find an unused index from after the current record index. */ for ( i = cur + 1; i < end; ++i ) { ridx = &ri->mapbase[i]; if ( (ridx->type[0] == 0) && (ridx->type[1] == 0) ) { /* Move index to make a space just after cur. */ nrec = shiftDownRIdx(ri->mapbase, cur + 1, i); fmpSetRIdxMapFlag(ri, MD_WRITE); /* Move the idxadr of the RCB of the moved record. */ fmpShiftIdxAdrRCB(rcb, TSD_SIA_RC2_M1, 1, nrec, 1); return E_OK; } if ( (ridx->type[0] == 0) && (ridx->type[1] != 0) ) { arec++; } } /* Find an unused index from before the current record index. */ for ( i = cur - 1; i >= top; --i ) { ridx = &ri->mapbase[i]; if ( (ridx->type[0] == 0) && (ridx->type[1] == 0) ) { /* Move index to make a space at the location of cur. */ nrec = shiftUpRIdx(ri->mapbase, i, cur); fmpSetRIdxMapFlag(ri, MD_WRITE); /* Move the idxadr of the RCB of the moved record. */ fmpShiftIdxAdrRCB(rcb, TSD_SIA_RC2_M1, -(nrec - 1), 0, TSD_SIA_RC5_M1); /* Since the current record index moved to the previous location, move ri to the previous location as well. */ ri->adr.ridx.offset = (VP)((VB*)ri->adr.ridx.offset - sizeof(DfRecordIndex)); ri->mapadr--; return E_OK; } } /* Add the block for new record index. */ err = appendRIdxBlock(ri, rcb, arec); if ( err < E_OK ) { goto err_ret; } nrec = (W)err; /* Divide the current record index block. */ err = divideRIdxBlock(ri, cur + 1); if ( err < E_OK ) { goto err_ret; } nrec += (W)err; /* Make invalid the RCBs of records moved between the index blocks. */ fmpSetInvalidRCB(rcb, 1, nrec); return E_OK;err_ret: DEBUG_PRINT(("appendRIdx err = %d\n", err)); return err;}/* * Add the record index. * Add new record index just after the current location of ri. * The added record index is cleared to 0 * Define the location of newly added record index as the current location of ri. * Return the address of newly added record index. */EXPORT DfRecordIndex* fmpAppendRIdx( RIdx *ri, RCB *rcb ){ DfRecordIndex *ridx; ER err; /* Add the record index. */ err = appendRIdx(ri, rcb); if ( err < E_OK ) { goto err_ret; } err = fmpCheckDiskError(ri->ofcb, ri->ofcb->fsinfo); if ( err < E_OK ) { goto err_ret; } /* Advance the current location by one. (Locate it at the added record.) */ ridx = fmpGetRIdx(ri); ri->cp = 0; return ridx;err_ret: /* Make invalid all RCBs for safety. */ fmpSetInvalidAllRCB(ri->ofcb); DEBUG_PRINT(("fmpAppendRIdx err = %d\n", err)); ri->err = err; return NULL;}/* * Insert the record index. * Insert the new record index at the current location of ri. * The inserted record index is cleared to 0 * The current location of ri is the location of inserted record index. */LOCAL ER insertRIdx( RIdx *ri, RCB *rcb ){ DfRecordIndex *ridx; W cur, top, end, i, k; W nrec, arec; ER err; cur = (ri->mapadr - ri->mapbase) - 1; top = (W)TopRIdx(ri->ofcb->idxlv, ri->ofcb); end = (W)(ri->ofcb->fsinfo->sblk / sizeof(DfRecordIndex)); /* 1 when the current location of ri is a normal index/link index. */ k = ( ri->mapbase[cur].type[0] == 0 )? 1: 0; arec = 0; /* Record count after the current record. */ /* Find an unused index from after the current record index. */ for ( i = cur + 1; i < end; ++i ) { ridx = &ri->mapbase[i]; if ( (ridx->type[0] == 0) && (ridx->type[1] == 0) ) { /* Move index to make a space at the location of cur. */ nrec = shiftDownRIdx(ri->mapbase, cur, i); fmpSetRIdxMapFlag(ri, MD_WRITE); /* Move the idxadr of the RCB of the moved record. */ fmpShiftIdxAdrRCB(rcb, TSD_SIA_RC2_M1, 1 - k, nrec - k, 1); return E_OK; } if ( (ridx->type[0] == 0) && (ridx->type[1] != 0) ) { arec++; } } /* Find an unused index from before the current record index. */ for ( i = cur - 1; i >= top; --i ) { ridx = &ri->mapbase[i]; if ( (ridx->type[0] == 0) && (ridx->type[1] == 0) ) { /* Move index to make a space just before cur. */ nrec = shiftUpRIdx(ri->mapbase, i, cur - 1); fmpSetRIdxMapFlag(ri, MD_WRITE); /* Move the idxadr of the RCB of the moved record. */ fmpShiftIdxAdrRCB(rcb, TSD_SIA_RC2_M1, -(nrec - 1) - k, 0 - k, TSD_SIA_RC5_M1); /* Since the inserted new index is in the previous location, move ri to the previous location as well. */ ri->adr.ridx.offset = (VP)((VB*)ri->adr.ridx.offset - sizeof(DfRecordIndex)); ri->mapadr--; return E_OK; } } /* Add the block for new record index. */ err = appendRIdxBlock(ri, rcb, arec); if ( err < E_OK ) { goto err_ret; } nrec = (W)err; /* Divide the current record index block. */ err = divideRIdxBlock(ri, cur); if ( err < E_OK ) { goto err_ret; } nrec += (W)err; /* Make invalid the RCBs of records moved between the index blocks. */ fmpSetInvalidRCB(rcb, 1 - k, nrec - k); return E_OK;err_ret: DEBUG_PRINT(("insertRIdx err = %d\n", err)); return err;}/* * Insert the record index. * Insert the new record index at the current location of ri. * The inserted record index is cleared to 0 * Define the location of newly inserted record index as the current location of ri. * Return the address of newly inserted record index. */EXPORT DfRecordIndex* fmpInsertRIdx( RIdx *ri, RCB *rcb ){ ER err; /* Insert the record index. */ err = insertRIdx(ri, rcb); if ( err < E_OK ) { goto err_ret; } err = fmpCheckDiskError(ri->ofcb, ri->ofcb->fsinfo); if ( err < E_OK ) { goto err_ret; } ri->cp = 0; return ri->mapadr - 1;err_ret: /* Make invalid all RCBs for safety. */ fmpSetInvalidAllRCB(ri->ofcb); DEBUG_PRINT(("fmpInsertRIdx err = %d\n", err)); ri->err = err; return NULL;}/* ------------------------------------------------------------------------ *//* * Change the record count of the indirect index. * Increase/Decrease the record count recorded in the indirect index * of the path of *idxadr by diff. */LOCAL ER changeRecordCountIIdx( IdxAdr *idxadr, W diff, OFCB *ofcb ){ FsInfo *fsinfo = ofcb->fsinfo; DfIndirectIndex *iidx; W i; W n; ID mid; ER err; for ( i = 0; i < ofcb->idxlv; ++i ) { iidx = fmpMapDskAdr(idxadr->iidx[i], sizeof(DfIndirectIndex), ofcb, &mid, fsinfo); if ( iidx == NULL ) { err = (ER)mid; goto err_ret; } n = (W)fmpConvEndianW(iidx->nrec, fsinfo) + diff; iidx->nrec = fmpConvEndianW((UW)n, fsinfo); fmpUnmapDisk(mid, MD_WRITE); } err = fmpCheckDiskError(ofcb, fsinfo); if ( err < E_OK ) { goto err_ret; } return E_OK;err_ret: DEBUG_PRINT(("changeRecordCountIIdx err = %d\n", err)); return err;}/* * Set the record index. * Set the record index at the current location of ri as a normal index or link index. * The set record index must be unused index cleared to 0. * * lnk is used only when setting the link index. */EXPORT ER fmpSetRIdx( RIdx *ri, W rtype, UH stype, LINK *lnk ){ DfRecordIndex *ridx = ri->mapadr - 1; OFCB *ofcb = ri->ofcb; FsInfo *fsinfo = ofcb->fsinfo; ER err; /* Set the indirect index to "record added." */ err = changeRecordCountIIdx(&ri->adr, +1, ofcb); if ( err < E_OK ) { goto err_ret; } /* Set the record index. */ if ( isLinkRecord(rtype) != 0 ) { /* When it is the link index. */ ridx->l.always80 = TSD_FSI_ALW_0X80; ridx->l.stype = fmpConvEndianH(stype, fsinfo); ridx->l.fid = fmpConvEndianH(lnk->f_id, fsinfo); ridx->l.atr[TSD_FSI_POS_0] = fmpConvEndianH(lnk->atr1, fsinfo); ridx->l.atr[TSD_FSI_POS_1] = fmpConvEndianH(lnk->atr2, fsinfo); ridx->l.atr[TSD_FSI_POS_2] = fmpConvEndianH(lnk->atr3, fsinfo); ridx->l.atr[TSD_FSI_POS_3] = fmpConvEndianH(lnk->atr4, fsinfo); ridx->l.atr[TSD_FSI_POS_4] = fmpConvEndianH(lnk->atr5, fsinfo); } else { /* When it is the normal index. */ ridx->n.rtype = (UB)rtype | TSD_FSI_RTY_0X80; ridx->n.stype = fmpConvEndianH(stype, fsinfo); } fmpSetRIdxMapFlag(ri, MD_WRITE); err = fmpCheckDiskError(ofcb, fsinfo); if ( err < E_OK ) { goto err_ret; } return E_OK;err_ret: DEBUG_PRINT(("fmpSetRIdx err = %d\n", err)); ri->err = err; return err;}/* ------------------------------------------------------------------------ *//* * Delete the record index block. * Delete the index block at the current location of ri. * * Although current location of ri become undecided, the next record index * can be read in the next reading (fmpGetRIdx/fmpGetDataBlkAdr). * (Similar state to the state just after fmpOpenRIdx) */LOCAL ER deleteRIdxBlock( RIdx *ri ){ IdxAdr idxadr; W delblk; LogAdr ladr; DfIndirectIndex *iidx, *base, *end; BOOL empty; W i; OFCB *ofcb = ri->ofcb; FsInfo *fsinfo = ofcb->fsinfo; ID mid; ER err; /* Index block to be deleted */ idxadr = fmpGetIdxAdr(ri); delblk = (W)ri->lblk; /* Move the current location of ri to the next index block. */ err = gotoNextRIdxBlk(ri); if ( (err < E_OK) && (err != E_ILFMT) ) { goto err_ret; } ri->cp = TSD_RID_CP_5; /* Delete */ for ( i = ofcb->idxlv - 1; i >= 0; --i ) { ladr = fmpDAdrToLAdr(idxadr.iidx[i], fsinfo); /* Map the indirect index block. */ base = fmpMapLogBlk(ladr.blk, ofcb, &mid, fsinfo); if ( base == NULL ) { err = (ER)mid; goto err_ret; } /* Delete the entry from the indirect index. */ iidx = (DfIndirectIndex*)((VB*)base + ladr.offset); iidx->blk = 0; /* Whether the indirect index block becomes free. */ iidx = &base[TopIIdx(i, ofcb)]; end = (DfIndirectIndex*)((VB*)base + fsinfo->sblk); empty = TRUE; while ( iidx < end ) { if ( iidx->blk != 0U ) { empty = FALSE; break; } iidx++; } if ( empty && (i == 0) ) { /* Since the index of the file header becomes free, restore the index level to 0. */ DfFileHeader *fh = (DfFileHeader*)base; fh->idxlv = 0; ofcb->idxlv = 0; } fmpUnmapDisk(mid, MD_WRITE); err = fmpCheckDiskError(ofcb, fsinfo); if ( err < E_OK ) { goto err_ret; } /* Release the block. */ err = fmpFreeOneBlock((UW)delblk, ofcb, fsinfo); if ( err < E_OK ) { goto err_ret; } if ( !empty ) { break; } delblk = (W)ladr.blk; } return E_OK;err_ret: DEBUG_PRINT(("deleteRIdxBlock err = %d\n", err)); return err;}/* * Delete the record index. * Delete the record index at the current location of ri. * The record index must not include the data block. */EXPORT ER fmpDeleteRIdx( RIdx *ri ){ DfRecordIndex *ridx; DfRecordIndex *end; OFCB *ofcb = ri->ofcb; FsInfo *fsinfo = ofcb->fsinfo; ER err; ridx = ri->mapadr - 1; if ( (ridx->type[0] == 0) && (ridx->type[1] != 0) ) { /* Set the indirect index to "record deleted." */ err = changeRecordCountIIdx(&ri->adr, TSD_FDR_VAL_M1, ofcb); if ( err < E_OK ) { goto err_ret; } } /* Make the current record index unused. */ memset(ridx, 0, (size_t)sizeof(DfRecordIndex)); fmpSetRIdxMapFlag(ri, MD_WRITE); /* Whether the whole record index becomes free. */ ridx = &ri->mapbase[TopRIdx(ofcb->idxlv, ofcb)]; end = (DfRecordIndex*)((VB*)ri->mapbase + fsinfo->sblk); while ( ridx < end ) { if ( !((ridx->type[0] == 0) && (ridx->type[1] == 0)) ) { /* Not free */ break; } ridx++; } err = fmpCheckDiskError(ofcb, fsinfo); if ( err < E_OK ) { goto err_ret; } if ( ridx >= end ) { /* Since it became free, delete the index block. */ err = deleteRIdxBlock(ri); if ( err < E_OK ) { goto err_ret; } } return E_OK;err_ret: DEBUG_PRINT(("fmpDeleteRIdx err = %d\n", err)); ri->err = err; return err;}/* * Delete the date block. * Release from top th byte to just before end th byte of the block indicated by * the data block address at the current location of ri. The data block * address of the record index is changed to leave only the part before top th byte. * When end is not a boundary of the logical block, it must be * at the separator code of fragment. * When top is the start of the record data (Make the record size 0), * it must be that topf = TRUE. * When the whole record index becomes free, the record index is also deleted. * (Only when it is connection index.) */EXPORT ER fmpDeleteDataBlk( RIdx *ri, W top, W end, BOOL topf ){ DfRecordIndex *ridx; W cp; LogBlk lblk; W useblk; W i, c; ER err; /* Current record index. */ ridx = fmpGetMapAdr(ri, &cp); /* Data block address */ lblk = fmpConvEndianLogBlk(ridx->c.blk[cp], ri->ofcb->fsinfo); /* Release data block */ useblk = fmpFreeDataBlk(lblk, top, end, topf, ri->ofcb); if ( useblk < E_OK ) { err = (ER)useblk; goto err_ret; } fmpSetRIdxMapFlag(ri, MD_WRITE); if ( useblk > 0 ) { ridx->c.blk[cp].cnt = useblk; /* Remaining block count */ } else { *(UW*)&ridx->c.blk[cp] = 0; /* Delete all. */ /* Whether the whole record index becomes free. */ c = 0; for ( i = 0; i < TSD_FDB_VAL_4; ++i ) { c += ridx->c.blk[i].cnt; } if ( (c == 0) && (ridx->type[1] == 0) ) { /* Delete the record index. */ err = fmpDeleteRIdx(ri); if ( err < E_OK ) { goto err_ret; } } } return E_OK;err_ret: DEBUG_PRINT(("fmpDeleteDataBlk err = %d\n", err)); ri->err = err; return err;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -