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

📄 rwrec.c

📁 T-kernel 的extension源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		goto err_ret;	}	/* Update the total byte count */	size = (W)fmpConvEndianW((UW)fh->size, fsinfo) + diffsize;	fh->size = (W)fmpConvEndianW((UW)size, fsinfo);	fmpUnmapDisk(mid, MD_WRITE);	err = fmpCheckDiskError(ofcb, fsinfo);	if ( err < E_OK ) {		goto err_ret;	}	return E_OK;err_ret:	DEBUG_PRINT(("changeFileSize err = %d\n", err));	return err;}/* * Move the data between the logical blocks. *	Copy the area from start th byte to just before end th byte of fromLBlk *	to the start of toLBlk, and free the source area. */LOCAL ER blockMove( UW toLBlk, UW fromLBlk, W start, W end, OFCB *ofcb ){	FsInfo	*fsinfo = ofcb->fsinfo;	VB	*to, *from;	ID	toMid, fromMid;	ER	err;	to = fmpMapLogBlk(toLBlk, ofcb, &toMid, fsinfo);	if ( to == NULL ) {		err = (ER)toMid;		goto err_ret1;	}	from = fmpMapLogBlk(fromLBlk, ofcb, &fromMid, fsinfo);	if ( from == NULL ) {		err = (ER)fromMid;		goto err_ret2;	}	/* Copy */	memcpy(to, from + start, (size_t)(end - start));	/* Free the data area of old block. */	err = fmpMergeFragment(fromLBlk, from, start, end, ofcb);	if ( err < E_OK ) {		goto err_ret3;	}	fmpUnmapDisk(fromMid, (UW)err);	fmpUnmapDisk(toMid, MD_WRITE);	return fmpCheckDiskError(ofcb, fsinfo);err_ret3:	fmpUnmapDisk(fromMid, MD_RDONLY);err_ret2:	fmpUnmapDisk(toMid, MD_WRITE);err_ret1:	DEBUG_PRINT(("blockCopy err = %d\n", err));	return err;}/* * Register the new block in the index record. *	Register it after dividing into parts of 255 or less blocks *	to conform to the format of the record index. *	Return the number of blocks that are successfully registered in *sz. (Also when error occurred) */LOCAL ER appendBlockRCB( RCB *rcb, RIdx *ri, LLogBlk lnew, W *sz ){	UW	adr, cnt;	LogBlk	new;	ER	err;	adr = lnew.adr;	cnt = lnew.cnt;	while ( cnt > TSD_ABR_CT1_255_U ) {		new.adr = adr;		new.cnt = TSD_ABR_CT1_255;		err = fmpAppendBlockRCB(rcb, ri, new);		if ( err < E_OK ) {			goto err_ret;		}		adr += TSD_ABR_CT1_255_U;		cnt -= TSD_ABR_CT1_255_U;	}	new.adr = adr;	new.cnt = cnt;	err = fmpAppendBlockRCB(rcb, ri, new);	if ( err < E_OK ) {		goto err_ret;	}	*sz = (W)lnew.cnt;	return E_OK;err_ret:	/* The number of blocks that are successfully registered. */	*sz = (W)(lnew.cnt - cnt);	/* Release the blocks that cannot be registered in the record index. */	lnew.adr = adr;	lnew.cnt = cnt;	(void)fmpFreeBlock(lnew, ri->ofcb);	DEBUG_PRINT(("appendBlockRCB err = %d\n", err));	return err;}/* * Reserve a free space from the fragment area to extend the record size. * However, when size is larger than the free space of the fragment area, * it is not allocated unless the end is a boundary of the logical block. * The current record size must be 0. */LOCAL WER expandRSizeFromFragmentSpace( RCB *rcb, W size, OFCB *ofcb ){	FsInfo		*fsinfo = ofcb->fsinfo;	W		keep;	DskAdr		dadr;	LogAdr		ladr;	DfNormalIndex	*nidx;	ID		mid;	ER		err;	/* Reserve a free space from the fragment area. */	keep = fmpAllocateFragment(&dadr, size, ofcb);	if ( keep < E_OK ) {		err = (ER)keep;		goto err_ret;	}	if ( keep > 0 ) {		/* Register in the record index */		nidx = fmpMapDskAdr(rcb->idxadr.ridx, sizeof(DfNormalIndex),							ofcb, &mid, fsinfo);		if ( nidx == NULL ) {			err = (ER)mid;			goto err_ret;		}		ladr = fmpDAdrToLAdr(dadr, fsinfo);		nidx->offset  = fmpConvEndianH((UH)ladr.offset, fsinfo);		nidx->size    = fmpConvEndianW((UW)keep, fsinfo);		nidx->blk.cnt = 1;		nidx->blk.adr = fmpConvEndian3B(ladr.blk, fsinfo);		fmpUnmapDisk(mid, MD_WRITE);		err = fmpCheckDiskError(ofcb, fsinfo);		if ( err < E_OK ) {			goto err_ret;		}		/* Update RCB */		rcb->rsize = keep;	}	return keep;err_ret:	DEBUG_PRINT(("expandRSizeFromFragmentSpace err = %d\n", err));	return err;}/* * Reserve a free space from just after the logical block located at the current * record end to extend the record size. However, when unable to extend * because there are other record data in the back in the end logical block, * copy the current data in the end logical block to the new logical block to extend it. */LOCAL WER expandRSizeFromLastBlock( RCB *rcb, W size, W units, OFCB *ofcb ){	FsInfo		*fsinfo = ofcb->fsinfo;	RIdx		ri;	DfRecordIndex	*ridx;	W		cp;	LogBlk		lb;	UW		lblk;	W		use, offset;	W		keep = 0;	ER		err;	err = fmpOpenRIdx(&ri, &rcb->idxadr, ofcb);	if ( err < E_OK ) {		goto err_ret1;	}	/* Find the logical block at the record end. */	use = fmpFindLastDataBlkAdr(&ri, &lb);	if ( use < E_OK ) {		err = (ER)use;		goto err_ret2;	}	/* Record index corresponding to the record end. */	ridx = fmpGetMapAdr(&ri, &cp);	/* Focus the address on one block at the end. */	if ( lb.cnt == 1 ) {		lblk = lb.adr;		offset = ( ridx->type[0] == 0 )?			fmpConvEndianH(ridx->n.offset, fsinfo): 0;	} else {		lblk = lb.adr + lb.cnt - 1U;		use = use - (fsinfo->sblk * (lb.cnt - 1));		offset = 0;	}	if ( use < fsinfo->sblk ) {		/* Reserve a free space of the end block. */		keep = fmpResizeFragment(lblk, use, size, ofcb);		if ( keep < E_OK ) {			err = (ER)keep;			goto err_ret2;		}		if ( keep == 0 ) {			/* Reserve new block,			   and copy the data of the end block. */			LLogBlk		new;			W		sz;			ER		apdErr;			size += use - offset;	/* Add the copied block size. */			/* Reserve new block. */			keep = fmpAllocateBlock(&new, size, units, lblk, ofcb);			if ( keep <= 0 ) {				err = (ER)keep;				goto err_ret2;			}			keep -= use - offset;			if ( offset > 0 ) {				/* Change the record start offset. */				ridx->n.offset = 0;			}			/* Deregister the end block from the record index. */			ridx->c.blk[cp].cnt--;			fmpSetRIdxMapFlag(&ri, MD_WRITE);			/* Resister the new block. */			apdErr = appendBlockRCB(rcb, &ri, new, &sz);			if ( apdErr < E_OK ) {				/* Set keep to the number of the blocks that successfully registered. */				keep = (sz * fsinfo->sblk) - (use - offset);				if ( sz <= 0 ) {					err = apdErr;					goto err_ret4;				}			}			/* Move the data from old block to new block. */			err = blockMove(new.adr, lblk, offset, use, ofcb);			if ( err < E_OK ) {				goto err_ret3;			}			if ( apdErr < E_OK ) {				err = apdErr;				goto err_ret3;			}		}	}	if ( keep > 0 ) {		/* Update the record size. */		err = fmpAddRSizeRCB(rcb, keep, ofcb);		if ( err < E_OK ) {			goto err_ret2;		}	}	err = fmpCloseRIdx(&ri);	if ( err < E_OK ) {		goto err_ret1;	}	return keep;err_ret4:	/* Restore the setting of the end record. */	if ( offset > 0 ) {		ridx->n.offset = fmpConvEndianH((UH)offset, fsinfo);	}	ridx->c.blk[cp].cnt++;err_ret3:	if ( keep > 0 ) {		/* Increase the record size as much as the reserved size. */		(void)fmpAddRSizeRCB(rcb, keep, ofcb);	}err_ret2:	(void)fmpCloseRIdx(&ri);err_ret1:	DEBUG_PRINT(("expandRSizeFromLastBlock err = %d\n", err));	return err;}/* * Reserve new free logical block to extend the record size. * Current record end must conform to a boundary of the logical block. * Return the reserved size to *size. (It is correctly set if not E_OK) */LOCAL ER expandRSizeFromNewBlock( RCB *rcb, W *size, W units, OFCB *ofcb ){	FsInfo		*fsinfo = ofcb->fsinfo;	RIdx		ri;	LogBlk		lb;	UW		lblk;	W		need = *size;	/* Size expected to be reserved */	W		keep = 0;	/* Size that has been reserved */	ER		err;	err = fmpOpenRIdx(&ri, &rcb->idxadr, ofcb);	if ( err < E_OK ) {		goto err_ret1;	}	/* Find the logical block at the record end. */	err = fmpFindLastDataBlkAdr(&ri, &lb);	if ( err < E_OK ) {		goto err_ret2;	}	/* Block number of the record end. (If the record is free, the block number is at an appropriate location.) */	if ( lb.cnt != 0 ) {		lblk = lb.adr + lb.cnt - 1U;	} else {		lblk = fmpGetMapBlkRIdx(&ri);	}	while ( keep < need ) {		LLogBlk		new;		W		alloc;		W		sz;		/* Reserve new block. */		alloc = fmpAllocateBlock(&new, need - keep, units, lblk, ofcb);		if ( alloc < E_OK ) {			err = (ER)alloc;			goto err_ret3;		}		/* Register the new block. */		err = appendBlockRCB(rcb, &ri, new, &sz);		if ( err < E_OK ) {			/* Add the number of the blocks that successfully registered to keep. */			keep += sz * fsinfo->sblk;			goto err_ret3;		}		keep += alloc;		lblk = new.adr + new.cnt - 1U;	}	if ( keep > 0 ) {		/* Update the record size. */		err = fmpAddRSizeRCB(rcb, keep, ofcb);		if ( err < E_OK ) {			goto err_ret2;		}	}	err = fmpCloseRIdx(&ri);	if ( err < E_OK ) {		goto err_ret1;	}	*size = keep;	return E_OK;err_ret3:	if ( keep > 0 ) {		/* Increase the record size as much as the reserved size. */		(void)fmpAddRSizeRCB(rcb, keep, ofcb);	}err_ret2:	(void)fmpCloseRIdx(&ri);err_ret1:	DEBUG_PRINT(("expandRSizeFromNewBlock err = %d\n", err));	*size = keep;	return err;}/* * Extend the record size. */LOCAL ER expandRecordSize( RCB *rcb, W rsize, UW units, OFCB *ofcb ){	W	keep, size;	ER	err;	units *= TSD_ERS_UNI_1024;	/* From KByte to Byte */	/* Size expected to be extended */	size = rsize - rcb->rsize;	keep = 0;	if ( (rcb->rsize == 0) && (units == 0U) ) {		/* Reserve from the fragment area. */		err = expandRSizeFromFragmentSpace(rcb, size, ofcb);		if ( err < E_OK ) {			goto err_ret2;		}		keep += (W)err;	}	if ( (size > keep) && (rcb->rsize > 0) ) {		/* Reserve from the logical block at the record end. */		err = expandRSizeFromLastBlock(rcb, size - keep, (W)units, ofcb);		if ( err < E_OK ) {			goto err_ret2;		}		keep += (W)err;	}	if ( size > keep ) {		W	sz = size - keep;		/* Reserve from the new logical block. */		err = expandRSizeFromNewBlock(rcb, &sz, (W)units, ofcb);		keep += sz;		if ( err < E_OK ) {			goto err_ret2;		}	}	/* Update the total byte count of the file of the file header. */	err = changeFileSize(ofcb, keep);	if ( err < E_OK ) {		goto err_ret1;	}	return E_OK;err_ret2:	if ( keep > 0 ) {		/* Increase the file size as much as the reserved size. */		(void)changeFileSize(ofcb, keep);	}err_ret1:	DEBUG_PRINT(("expandRecordSize err = %d\n", err));	return err;}/* ------------------------------------------------------------------------ *//* * Write the data record. *	offset, buf, size, and units are based on the parameter of wri_rec */EXPORT ER fmpWriteDataRecord( RCB *rcb, OFCB *ofcb,				W offset, B *buf, W size, UW units ){	W	rsize;	ER	err, error = E_OK;	/* Size of the whole record after writing the data. */	rsize = offset + size;	if ( rsize > rcb->rsize ) {		/* Extend the record size. */		err = expandRecordSize(rcb, rsize, units, ofcb);		if ( err < E_OK ) {			if ( err != E_NODSK ) {				goto err_ret;			}			error = err;		}	}	if ( buf != NULL ) {		/* Check the write buffer area. */		err = CheckSpaceR(buf, size);		if ( err < E_OK ) {			goto err_ret;		}		/* When the disk is full, write the record as much as the extended size. */		if ( rsize > rcb->rsize ) {			size = rcb->rsize - offset;		}		if ( size > 0 ) {			/* Write the record. */			err = rwDataRecord(buf, rcb, offset, size,							ofcb, Write);			if ( err < E_OK ) {				goto err_ret;			}

⌨️ 快捷键说明

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