/****************************************************************************** * * NSSDC/CDF CDF `delete' operations. * * Version 1.4b, 4-Mar-97, Hughes STX. * * Modification history: * * V1.0 20-May-92, J Love Original version (was part of `cdflib.c'). * V1.1 21-Aug-92, J Love CDF V2.3 (shareable/NeXT,zVar). * V1.2 30-Nov-93, J Love CDF V2.4. Readonly mode, deleting V1 CDFs on * all machines. * V1.3 5-Dec-94, J Love CDF V2.5. * V1.3a 6-Jan-95, J Love More cache-residency. * V1.3b 24-Feb-95, J Love Solaris 2.3 IDL i/f. * V1.4 5-Sep-96, J Love CDF V2.6. * V1.4a 21-Feb-97, J Love Removed RICE. * V1.4b 4-Mar-97, J Love Windows NT for MS Visual C/C++ on an IBM PC. * V2.0 08-Apr-04, M Liu Reset the current variable offset when that * variable is deleted. * V2.1 29-Jun-04, M Liu Added LFS (Large File Support > 2G). * ******************************************************************************/ #include "cdflib.h" #include "cdflib64.h" /****************************************************************************** * Local function prototypes. ******************************************************************************/ static CDFstatus WasteTree_r_64 PROTOARGs(( struct CDFstruct *CDF, OFF_T vxrOffset )); static CDFstatus DeleteVarRecords64 PROTOARGs(( struct CDFstruct *CDF, struct VarStruct *Var, Int32 firstRec, Int32 lastRec )); static CDFstatus DeleteRecords64 PROTOARGs(( struct CDFstruct *CDF, struct VarStruct *Var, Int32 firstRec, Int32 lastRec, Int32 *deletedTo )); static CDFstatus DeleteRecords_r_64 PROTOARGs(( struct CDFstruct *CDF, struct VarStruct *Var, OFF_T firstVXRoffset, Int32 firstRec, Int32 lastRec, Int32 *deletedTo, Logical *total )); static CDFstatus DeleteFromFront64 PROTOARGs(( struct CDFstruct *CDF, struct VarStruct *Var, Int32 last, OFF_T vxrOffset, struct VXRstruct64 *VXR, int entryN, OFF_T irSize )); static CDFstatus DeleteFromMiddle64 PROTOARGs(( struct CDFstruct *CDF, struct VarStruct *Var, Int32 first, Int32 last, OFF_T vxrOffset, struct VXRstruct64 *VXR, int entryN, OFF_T irSize )); static CDFstatus DeleteFromEnd64 PROTOARGs(( struct CDFstruct *CDF, struct VarStruct *Var, Int32 first, OFF_T vxrOffset, struct VXRstruct64 *VXR, int entryN, OFF_T irSize )); static CDFstatus DeleteVXRentry64 PROTOARGs(( struct CDFstruct *CDF, OFF_T firstVXRoffset, OFF_T delVXRoffset, int delEntryN, Logical *total )); static CDFstatus InsertIndexEntry64 PROTOARGs(( struct CDFstruct *CDF, OFF_T vxrOffset, int entryN, Logical after, Int32 first, Int32 last, OFF_T offset )); static CDFstatus UpdateIndexEntries_r_64 PROTOARGs(( vFILE *fp, OFF_T vxrOffset, Int32 aboveRecord, Int32 recordCount )); static CDFstatus WriteCVVRorVVR64 PROTOARGs(( struct CDFstruct *CDF, OFF_T cSize, OFF_T stageOffset, OFF_T uSize, OFF_T *newOffset )); /****************************************************************************** * CDFdel64. ******************************************************************************/ STATICforIDL CDFstatus CDFdel64 (Va, Cur) struct VAstruct *Va; struct CurStruct *Cur; { CDFstatus tStatus, pStatus = CDF_OK; switch (Va->item) { /**************************************************************************** * CDF_, delete an open CDF. ****************************************************************************/ case CDF_: { struct CDFstruct *CDF; SelectCDF (Cur->cdf, CDF) if (!WriteAccess64(CDF,TRUE,&pStatus)) return pStatus; sX (DeleteCDFfiles64(CDF), &pStatus); if (CDF->uDotFp != NULL) { if (!DELETEv64(CDF->uDotFp,NULL)) sX (SCRATCH_DELETE_ERROR, &pStatus); CDF->uDotFp = NULL; } if (CDF->stage.fp != NULL) { if (!DELETEv64(CDF->stage.fp,NULL)) sX (SCRATCH_DELETE_ERROR, &pStatus); CDF->stage.fp = NULL; } if (CDF->compressFp != NULL) { if (!DELETEv64(CDF->compressFp,NULL)) sX (SCRATCH_DELETE_ERROR, &pStatus); CDF->compressFp = NULL; } FreeCDFid (CDF, FALSE); Cur->cdf = NULL; break; } /**************************************************************************** * zVAR_/rVAR_ ****************************************************************************/ case zVAR_: case rVAR_: { Logical zOp = (Va->item == zVAR_), zVar; struct CDFstruct *CDF; struct VDRstruct64 VDR, VDRt; Int32 rMaxRec = NO_RECORD; Int32 scope, entryN, nVars; int varN; OFF_T vOffset, tOffset, aOffset, eOffset, VDRhead; /************************************************************************** * Get pointer to current CDF and locate the current r/zVariable. **************************************************************************/ SelectCDF (Cur->cdf, CDF) if (!CDF->singleFile) return UNSUPPORTED_OPERATION; if (BADzOP(CDF,!zOp)) return ILLEGAL_IN_zMODE; if (!CURRENTvarSELECTED(CDF,zOp)) return NO_VAR_SELECTED; /************************************************************************** * Switch to write access. **************************************************************************/ if (!WriteAccess64(CDF,FALSE,&pStatus)) return pStatus; /* if (!sX(LocateCurrentVar64(CDF,zOp,&vOffset,&zVar,NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } */ zVar = CurrentVarMode(CDF,zOp); if (zModeON(CDF) || zVar) vOffset = CDF->CURzVarOffset64; else vOffset = CDF->CURrVarOffset64; /************************************************************************** * Read/get GDR field(s). **************************************************************************/ if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64, BOO(zVar,GDR_zVDRHEAD,GDR_rVDRHEAD),&VDRhead, GDR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } nVars = BOO(zVar,CDF->NzVars,CDF->NrVars); /************************************************************************** * Read the VDR. **************************************************************************/ if (!sX(ReadVDR64(CDF,CDF->fp,vOffset,zVar, VDR_RECORD,&VDR,NULL, VDR_NULL),&pStatus)){ AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } /************************************************************************** * Remove the VDR from the list of r/zVariables and decrement the number * of r/zVariables. If this is a true rVariable, check for the maximum * record number written for the rVariables up to the one being deleted. **************************************************************************/ if (VDRhead == vOffset) VDRhead = VDR.VDRnext; else { tOffset = VDRhead; while (tOffset != 0) { if (!sX(ReadVDR64(CDF,CDF->fp,tOffset,zVar, VDR_RECORD,&VDRt,NULL, VDR_NULL),&pStatus)){ AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } if (!zVar) rMaxRec = MAXIMUM (rMaxRec, VDRt.MaxRec); if (VDRt.VDRnext == vOffset) { VDRt.VDRnext = VDR.VDRnext; if (!sX(WriteVDR64(CDF,CDF->fp,tOffset,zVar, VDR_RECORD,&VDRt,NULL, VDR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } break; } tOffset = VDRt.VDRnext; } if (tOffset == 0) { AbortAccess64 (CDF, UPDATE, noDELETE); return CORRUPTED_V3_CDF; } } nVars--; /************************************************************************** * Renumber following VDRs. If this is a true rVariable, continue checking * for the maximum record number written. **************************************************************************/ tOffset = VDR.VDRnext; while (tOffset != 0) { if (!sX(ReadVDR64(CDF,CDF->fp,tOffset,zVar, VDR_RECORD,&VDRt,NULL, VDR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } if (!zVar) rMaxRec = MAXIMUM (rMaxRec, VDRt.MaxRec); VDRt.Num--; if (!sX(WriteVDR64(CDF,CDF->fp,tOffset,zVar, VDR_RECORD,&VDRt,NULL, VDR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } tOffset = VDRt.VDRnext; } /************************************************************************** * Write/store the GDR fields that may have changed. **************************************************************************/ if (!zVar) { CDF->rMaxRec = rMaxRec; if (!sX(WriteGDR64(CDF->fp,CDF->GDRoffset64, GDR_rMAXREC,&rMaxRec, GDR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } } if (!sX(WriteGDR64(CDF->fp,CDF->GDRoffset64, BOO(zVar,GDR_zVDRHEAD,GDR_rVDRHEAD),&VDRhead, BOO(zVar,GDR_NzVARS,GDR_NrVARS),&nVars, GDR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } if (zVar) CDF->NzVars = nVars; else CDF->NrVars = nVars; /************************************************************************** * Waste VDR. **************************************************************************/ if (!sX(WasteIR64(CDF,vOffset,VDR.RecordSize),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } /************************************************************************** * Waste CPR/SPR (if one exists). **************************************************************************/ if (VDR.CPRorSPRoffset != (OFF_T) NO_OFFSET64) { OFF_T irSize; if (!sX(ReadIrSize64(CDF->fp, VDR.CPRorSPRoffset, &irSize),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } if (!sX(WasteIR64(CDF,VDR.CPRorSPRoffset,irSize),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } } /************************************************************************** * Waste VXRs and VVRs/CVVRs. **************************************************************************/ if (!sX(WasteTree_r_64(CDF,VDR.VXRhead),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } /************************************************************************** * Free/adjust variable data structures kept in memory. Note that the * number of z/rVariables has already been decremented. **************************************************************************/ if (zVar) { if (CDF->zVars[(int)VDR.Num] != NULL) { cdf_FreeMemory (CDF->zVars[(int)VDR.Num], NULL); } for (varN = (int) VDR.Num; varN < nVars; varN++) { CDF->zVars[varN] = CDF->zVars[varN+1]; if (CDF->zVars[varN] != NULL) CDF->zVars[varN]->varN = varN; } CDF->zVars[varN] = NULL; } else { if (CDF->rVars[(int)VDR.Num] != NULL) { cdf_FreeMemory (CDF->rVars[(int)VDR.Num], NULL); } for (varN = (int) VDR.Num; varN < nVars; varN++) { CDF->rVars[varN] = CDF->rVars[varN+1]; if (CDF->rVars[varN] != NULL) CDF->rVars[varN]->varN = varN; } CDF->rVars[varN] = NULL; } /************************************************************************** * Reset the current r/zVariable number. **************************************************************************/ if (zOp) { CDF->CURzVarNum = RESERVED_VARNUM; CDF->CURzVarOffset64 = (OFF_T) 0; } else { CDF->CURrVarNum = RESERVED_VARNUM; CDF->CURrVarOffset64 = (OFF_T) 0; } /************************************************************************** * Delete the associated attribute entries and renumber the entries that * are associated with the variables that followed the variable that was * deleted. **************************************************************************/ if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64, GDR_ADRHEAD,&aOffset, GDR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } while (aOffset != 0) { /************************************************************************ * Read the scope of the attribute. ************************************************************************/ if (!sX(ReadADR64(CDF->fp,aOffset, ADR_SCOPE,&scope, ADR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } if (VARIABLEscope(scope)) { Int32 maxEntry = NO_ENTRY; /********************************************************************** * Delete associated entry. **********************************************************************/ tStatus = FindEntryByNumber64 (CDF, aOffset, zVar, VDR.Num, &eOffset); switch (tStatus) { case CDF_OK: if (!sX(DeleteEntry64(CDF,aOffset,eOffset),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } break; case NO_SUCH_ENTRY: break; default: AbortAccess64 (CDF, UPDATE, noDELETE); return tStatus; } /********************************************************************** * Renumber entries. Note that the entry numbers are not necessarily * increasing. (The entries may have been written in any order.) Also * determine the new maximum entry number. **********************************************************************/ if (!sX(ReadADR64(CDF->fp,aOffset, BOO(zVar,ADR_AzEDRHEAD,ADR_AgrEDRHEAD),&eOffset, ADR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } while (eOffset != 0) { if (!sX(ReadAEDR64(CDF->fp,eOffset, AEDR_NUM,&entryN, AEDR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } if (entryN > VDR.Num) { entryN--; if (!sX(WriteAEDR64(CDF,CDF->fp,eOffset, AEDR_NUM,&entryN, AEDR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } } maxEntry = MAXIMUM (maxEntry, entryN); if (!sX(ReadAEDR64(CDF->fp,eOffset, AEDR_AEDRNEXT,&eOffset, AEDR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } } /********************************************************************** * Write new maximum entry number to the ADR. **********************************************************************/ if (!sX(WriteADR64(CDF->fp,aOffset, BOO(zVar,ADR_MAXzENTRY,ADR_MAXgrENTRY),&maxEntry, ADR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } } /************************************************************************ * Read offset of next ADR. ************************************************************************/ if (!sX(ReadADR64(CDF->fp,aOffset, ADR_ADRNEXT,&aOffset, ADR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } } /************************************************************************** * Reset the current entry offset (in case it was affected). **************************************************************************/ if (!sX(BOO(zOp,SetCURzEntry64(CDF,FALSE,CDF->CURzEntryNum), SetCURgrEntry64(CDF,FALSE,CDF->CURgrEntryNum)),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } break; } /**************************************************************************** * rVAR_RECORDS_/zVAR_RECORDS_, ****************************************************************************/ case rVAR_RECORDS_: case zVAR_RECORDS_: { Logical zOp = (Va->item == zVAR_RECORDS_); struct CDFstruct *CDF; struct VarStruct *Var; Int32 firstRec = (Int32) va_arg (Va->ap, long); Int32 lastRec = (Int32) va_arg (Va->ap, long); SelectCDF (Cur->cdf, CDF) if (BADzOP(CDF,!zOp)) return ILLEGAL_IN_zMODE; if (!CURRENTvarSELECTED(CDF,zOp)) return NO_VAR_SELECTED; if (!CDF->singleFile) { sX (MULTI_FILE_FORMAT, &pStatus); break; } if (firstRec < 0) return BAD_REC_NUM; if (lastRec < 0) return BAD_REC_NUM; if (lastRec < firstRec) return BAD_REC_NUM; if (!WriteAccess64(CDF,FALSE,&pStatus)) return pStatus; if (!sX(InitCurrentVar64(CDF,zOp,&Var),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } if (!sX(DeleteVarRecords64(CDF,Var,firstRec,lastRec),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } break; } /**************************************************************************** * ATTR_ ****************************************************************************/ case ATTR_: { struct CDFstruct *CDF; OFF_T tOffset; struct GDRstruct64 GDR; struct ADRstruct64 ADR, ADRt; struct AEDRstruct64 AEDRt; /************************************************************************** * Get pointer to current CDF and locate the current attribute. **************************************************************************/ SelectCDF (Cur->cdf, CDF) if (!CURRENTattrSELECTED64(CDF)) return NO_ATTR_SELECTED; /************************************************************************** * Read the GDR and ADR. **************************************************************************/ if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64, GDR_RECORD,&GDR, GDR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } if (!sX(ReadADR64(CDF->fp,CDF->CURattrOffset64, ADR_RECORD,&ADR, ADR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } /************************************************************************** * Switch to write access. **************************************************************************/ if (!WriteAccess64(CDF,FALSE,&pStatus)) return pStatus; /************************************************************************** * Remove the ADR from the list of attributes and decrement the number of * attributes. **************************************************************************/ if (GDR.ADRhead == CDF->CURattrOffset64) GDR.ADRhead = ADR.ADRnext; else { tOffset = GDR.ADRhead; while (tOffset != 0) { if (!sX(ReadADR64(CDF->fp,tOffset, ADR_RECORD,&ADRt, ADR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } if (ADRt.ADRnext == CDF->CURattrOffset64) break; tOffset = ADRt.ADRnext; } if (tOffset == 0) { AbortAccess64 (CDF, UPDATE, noDELETE); return CORRUPTED_V3_CDF; } ADRt.ADRnext = ADR.ADRnext; if (!sX(WriteADR64(CDF->fp,tOffset, ADR_RECORD,&ADRt, ADR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } } GDR.NumAttr--; if (!sX(WriteGDR64(CDF->fp,CDF->GDRoffset64, GDR_RECORD,&GDR, GDR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } /************************************************************************** * Renumber each of the following attributes. **************************************************************************/ tOffset = ADR.ADRnext; while (tOffset != 0) { if (!sX(ReadADR64(CDF->fp,tOffset, ADR_RECORD,&ADRt, ADR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } ADRt.Num--; if (!sX(WriteADR64(CDF->fp,tOffset, ADR_RECORD,&ADRt, ADR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } tOffset = ADRt.ADRnext; } /************************************************************************** * Waste the ADR and each of the AgrEDR and AzEDR's for the attribute. **************************************************************************/ if (!sX(WasteIR64(CDF,CDF->CURattrOffset64,ADR.RecordSize),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } tOffset = ADR.AgrEDRhead; while (tOffset != 0) { if (!sX(ReadAEDR64(CDF->fp,tOffset, AEDR_RECORD,&AEDRt,NULL, AEDR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } if (!sX(WasteIR64(CDF,tOffset,AEDRt.RecordSize),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } tOffset = AEDRt.AEDRnext; } tOffset = ADR.AzEDRhead; while (tOffset != 0) { if (!sX(ReadAEDR64(CDF->fp,tOffset, AEDR_RECORD,&AEDRt,NULL, AEDR_NULL),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } if (!sX(WasteIR64(CDF,tOffset,AEDRt.RecordSize),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } tOffset = AEDRt.AEDRnext; } /************************************************************************** * Reset the current attribute offset and current entry offsets. **************************************************************************/ CDF->CURattrOffset64 = (OFF_T) RESERVED_ATTROFFSET64; CDF->CURgrEntryOffset64 = (OFF_T) RESERVED_ENTRYOFFSET64; CDF->CURzEntryOffset64 = (OFF_T) RESERVED_ENTRYOFFSET64; break; } /**************************************************************************** * gENTRY_/zENTRY_/rENTRY_ ****************************************************************************/ case gENTRY_: case zENTRY_: case rENTRY_: { int entryType = E3p(Va->item,gENTRY_,rENTRY_,zENTRY_); struct CDFstruct *CDF; OFF_T eOffset; /************************************************************************** * Get pointer to current CDF, locate the current attribute, and verify * that a current entry number has been selected. **************************************************************************/ SelectCDF (Cur->cdf, CDF) if (!CURRENTattrSELECTED64(CDF)) return NO_ATTR_SELECTED; if (E3(entryType, CDF->CURgrEntryNum, CDF->CURgrEntryNum, CDF->CURzEntryNum) == RESERVED_ENTRYNUM) return NO_ENTRY_SELECTED; /************************************************************************** * Verify that the operation being performed is legal for the attribute's * scope. **************************************************************************/ if (!sX(CheckEntryOp64(CDF,entryType),&pStatus)) return pStatus; /************************************************************************** * Switch to write access. **************************************************************************/ if (!WriteAccess64(CDF,FALSE,&pStatus)) return pStatus; /************************************************************************** * Locate the entry to be deleted. **************************************************************************/ eOffset = E3(entryType,CDF->CURgrEntryOffset64, CDF->CURgrEntryOffset64, CDF->CURzEntryOffset64); if (eOffset == (OFF_T) RESERVED_ENTRYOFFSET64) return NO_SUCH_ENTRY; /************************************************************************** * Delete the entry. **************************************************************************/ if (!sX(DeleteEntry64(CDF,CDF->CURattrOffset64,eOffset),&pStatus)) { AbortAccess64 (CDF, UPDATE, noDELETE); return pStatus; } /************************************************************************** * Reset the current entry offset (to indicate the entry no longer exists). **************************************************************************/ switch (entryType) { case gENTRYt: case rENTRYt: CDF->CURgrEntryOffset64 = (OFF_T) RESERVED_ENTRYOFFSET64; break; case zENTRYt: CDF->CURzEntryOffset64 = (OFF_T) RESERVED_ENTRYOFFSET64; break; } break; } /**************************************************************************** * Unknown item, must be the next function. ****************************************************************************/ default: { Va->fnc = Va->item; break; } } return pStatus; } /****************************************************************************** * WasteTree_r_64. ******************************************************************************/ static CDFstatus WasteTree_r_64 (CDF, vxrOffset) struct CDFstruct *CDF; OFF_T vxrOffset; { CDFstatus pStatus = CDF_OK; int e; struct VXRstruct64 VXR; Int32 irType; OFF_T irSize; while (vxrOffset != (OFF_T) ZERO_OFFSET64) { if (!sX(ReadVXR64(CDF->fp,vxrOffset, VXR_RECORD,&VXR, VXR_NULL),&pStatus)) return pStatus; if (!sX(WasteIR64(CDF,vxrOffset,VXR.RecordSize),&pStatus)) return pStatus; for (e = 0; e < VXR.NusedEntries; e++) { if (!sX(ReadIrType64(CDF->fp, VXR.Offset[e], &irType),&pStatus)) return pStatus; switch (irType) { case VXR_: if (!sX(WasteTree_r_64(CDF,VXR.Offset[e]),&pStatus)) return pStatus; break; case VVR_: case CVVR_: if (!sX(ReadIrSize64(CDF->fp, VXR.Offset[e], &irSize),&pStatus)) return pStatus; if (!sX(WasteIR64(CDF, VXR.Offset[e], irSize),&pStatus)) return pStatus; break; default: return CORRUPTED_V3_CDF; } } vxrOffset = VXR.VXRnext; } return pStatus; } /****************************************************************************** * DeleteVarRecords64. ******************************************************************************/ static CDFstatus DeleteVarRecords64 (CDF, Var, firstRec, lastRec) struct CDFstruct *CDF; struct VarStruct *Var; Int32 firstRec; Int32 lastRec; { CDFstatus pStatus = CDF_OK; Int32 deletedTo, recNum; Logical found; /**************************************************************************** * Base on the variable type... ****************************************************************************/ switch (Var->vType) { /************************************************************************** * Standard variable in a single-file CDF. **************************************************************************/ case STANDARD_: { Int32 aboveRecord, deleteCount; OFF_T vxrHead; /************************************************************************ * Verify/adjust the records to be deleted. ************************************************************************/ if (firstRec > Var->maxAllocated) return pStatus; lastRec = MINIMUM(lastRec,Var->maxAllocated); /************************************************************************ * Delete the records. ************************************************************************/ for (recNum = firstRec; recNum <= lastRec; recNum = deletedTo + 1) { if (!sX(DeleteRecords64(CDF,Var,recNum, lastRec,&deletedTo),&pStatus)) return pStatus; } deleteCount = lastRec - firstRec + 1; /************************************************************************ * Update the index entries. ************************************************************************/ aboveRecord = firstRec - 1; if (!sX(ReadVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar, VDR_VXRHEAD,&vxrHead, VDR_NULL),&pStatus)) return pStatus; if (!sX(UpdateIndexEntries_r_64(CDF->fp,vxrHead, aboveRecord, deleteCount),&pStatus)) return pStatus; /************************************************************************ * Update the control information. ************************************************************************/ if (firstRec <= Var->maxWritten) { if (lastRec > Var->maxWritten) Var->maxWritten = firstRec - 1; else Var->maxWritten -= deleteCount; } if (firstRec <= Var->maxAllocated) { if (lastRec > Var->maxAllocated) Var->maxAllocated = firstRec - 1; else Var->maxAllocated -= deleteCount; } /************************************************************************ * Update the maximum record field in the VDR. ************************************************************************/ if (firstRec <= Var->maxRec) { if (lastRec > Var->maxRec) Var->maxRec = firstRec - 1; else Var->maxRec -= deleteCount; if (!sX(WriteVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar, VDR_MAXREC,&(Var->maxRec), VDR_NULL),&pStatus)) return pStatus; } break; } /************************************************************************** * Sparse records. **************************************************************************/ case SPARSE_RECORDS_: /************************************************************************ * Flush staging area first. This will automatically clear the staging * area as well. ************************************************************************/ if (!sX(FlushStage64(CDF,Var),&pStatus)) return pStatus; /************************************************************************ * Verify/adjust the records to be deleted. ************************************************************************/ if (firstRec > Var->maxAllocated) return pStatus; lastRec = MINIMUM(lastRec,Var->maxAllocated); /************************************************************************ * Delete the records. ************************************************************************/ for (recNum = firstRec; recNum <= lastRec; recNum = deletedTo + 1) { if (!sX(DeleteRecords64(CDF,Var,recNum, lastRec,&deletedTo),&pStatus)) return pStatus; } /************************************************************************ * Update the control information. ************************************************************************/ if (INCLUSIVE(firstRec,Var->maxWritten,lastRec)) { if (!sX(PrevRecord64(CDF,Var->VDRoffset64,Var->zVar, (Int32)(firstRec - 1), &(Var->maxWritten),&found),&pStatus)) return pStatus; if (!found) Var->maxWritten = NO_RECORD; } if (INCLUSIVE(firstRec,Var->maxAllocated,lastRec)) { if (!sX(PrevRecord64(CDF,Var->VDRoffset64,Var->zVar, (Int32)(firstRec - 1), &(Var->maxAllocated),&found),&pStatus)) return pStatus; if (!found) Var->maxAllocated = NO_RECORD; } /************************************************************************ * Update the maximum record field in the VDR. ************************************************************************/ if (INCLUSIVE(firstRec,Var->maxRec,lastRec)) { if (!sX(PrevRecord64(CDF,Var->VDRoffset64,Var->zVar, (Int32)(firstRec - 1), &(Var->maxRec),&found),&pStatus)) return pStatus; if (!found) Var->maxRec = NO_RECORD; if (!sX(WriteVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar, VDR_MAXREC,&(Var->maxRec), VDR_NULL),&pStatus)) return pStatus; } break; /************************************************************************** * Compressed records. **************************************************************************/ case COMPRESSED_: { Int32 aboveRecord, deleteCount; OFF_T vxrHead; /************************************************************************ * Flush/clear staging area first. ************************************************************************/ if (!sX(FlushStage64(CDF,Var),&pStatus)) return pStatus; Var->stage.firstRec = NO_RECORD; Var->stage.lastRec = NO_RECORD; Var->stage.dotOffset64 = (OFF_T) NO_OFFSET64; /************************************************************************ * Verify/adjust the records to be deleted. ************************************************************************/ if (firstRec > Var->maxRec) return pStatus; lastRec = MINIMUM(lastRec,Var->maxRec); /************************************************************************ * Delete the records. ************************************************************************/ for (recNum = firstRec; recNum <= lastRec; recNum = deletedTo + 1) { if (!sX(DeleteRecords64(CDF,Var,recNum, lastRec,&deletedTo),&pStatus)) return pStatus; } deleteCount = lastRec - firstRec + 1; /************************************************************************ * Update the index entries. ************************************************************************/ aboveRecord = firstRec - 1; if (!sX(ReadVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar, VDR_VXRHEAD,&vxrHead, VDR_NULL),&pStatus)) return pStatus; if (!sX(UpdateIndexEntries_r_64(CDF->fp,vxrHead, aboveRecord, deleteCount),&pStatus)) return pStatus; /************************************************************************ * Update the maximum record field in the VDR. ************************************************************************/ if (firstRec <= Var->maxRec) { if (lastRec > Var->maxRec) Var->maxRec = firstRec - 1; else Var->maxRec -= deleteCount; if (!sX(WriteVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar, VDR_MAXREC,&(Var->maxRec), VDR_NULL),&pStatus)) return pStatus; } break; } /************************************************************************** * Sparse compressed records. **************************************************************************/ case SPARSE_COMPRESSED_RECORDS_: /************************************************************************ * Flush/clear staging area first. ************************************************************************/ if (!sX(FlushStage64(CDF,Var),&pStatus)) return pStatus; Var->stage.firstRec = NO_RECORD; Var->stage.lastRec = NO_RECORD; Var->stage.dotOffset64 = (OFF_T) NO_OFFSET64; /************************************************************************ * Verify/adjust the records to be deleted. ************************************************************************/ if (firstRec > Var->maxRec) return pStatus; lastRec = MINIMUM(lastRec,Var->maxRec); /************************************************************************ * Delete the records. ************************************************************************/ for (recNum = firstRec; recNum <= lastRec; recNum = deletedTo + 1) { if (!sX(DeleteRecords64(CDF,Var,recNum, lastRec,&deletedTo),&pStatus)) return pStatus; } /************************************************************************ * Update the maximum record field in the VDR. ************************************************************************/ if (INCLUSIVE(firstRec,Var->maxRec,lastRec)) { if (!sX(PrevRecord64(CDF,Var->VDRoffset64,Var->zVar, (Int32)(firstRec - 1), &(Var->maxRec),&found),&pStatus)) return pStatus; if (!found) Var->maxRec = NO_RECORD; if (!sX(WriteVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar, VDR_MAXREC,&(Var->maxRec), VDR_NULL),&pStatus)) return pStatus; } break; /************************************************************************** * Oops. **************************************************************************/ default: return CDF_INTERNAL_ERROR; } /**************************************************************************** * Update the VXR tail field in the VDR. ****************************************************************************/ if (!sX(UpdateVXRtailInVDR64(CDF,Var),&pStatus)) return pStatus; /**************************************************************************** * Update the maximum record field in the GDR if an rVariable. This is * done in case this rVariable had the maximum record number. ****************************************************************************/ if (!Var->zVar) { Int32 maxRec; Logical zVar = FALSE; OFF_T vdrOffset; CDF->rMaxRec = NO_RECORD; if (!sX(ReadGDR64(CDF->fp,CDF->GDRoffset64, GDR_rVDRHEAD,&vdrOffset, GDR_NULL),&pStatus)) return pStatus; while (vdrOffset != (OFF_T) ZERO_OFFSET64) { if (!sX(ReadVDR64(CDF,CDF->fp,vdrOffset,zVar, VDR_MAXREC,&maxRec, VDR_VDRNEXT,&vdrOffset, VDR_NULL),&pStatus)) return pStatus; CDF->rMaxRec = MAXIMUM(CDF->rMaxRec,maxRec); } if (!sX(WriteGDR64(CDF->fp,CDF->GDRoffset64, GDR_rMAXREC,&(CDF->rMaxRec), GDR_NULL),&pStatus)) return pStatus; } return pStatus; } /****************************************************************************** * DeleteRecords64. ******************************************************************************/ static CDFstatus DeleteRecords64 (CDF, Var, firstRec, lastRec, deletedTo) struct CDFstruct *CDF; struct VarStruct *Var; Int32 firstRec; Int32 lastRec; Int32 *deletedTo; { CDFstatus pStatus = CDF_OK; Logical total = FALSE; OFF_T vxrOffset; /**************************************************************************** * Read offset of the first VXR... ****************************************************************************/ if (!sX(ReadVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar, VDR_VXRHEAD,&vxrOffset, VDR_NULL),&pStatus)) return pStatus; /**************************************************************************** * ...and start there. ****************************************************************************/ if (!sX(DeleteRecords_r_64(CDF,Var,vxrOffset,firstRec, lastRec,deletedTo,&total),&pStatus)) return pStatus; /**************************************************************************** * If the top level of VXR(s) was totally deleted, set the VXR head/tail to * ZERO_OFFSET. ****************************************************************************/ if (total) { OFF_T zeroOffset = (OFF_T) ZERO_OFFSET64; if (!sX(WriteVDR64(CDF,CDF->fp,Var->VDRoffset64,Var->zVar, VDR_VXRHEAD,&zeroOffset, VDR_VXRTAIL,&zeroOffset, VDR_NULL),&pStatus)) return pStatus; } return pStatus; } /****************************************************************************** * DeleteRecords_r_64. ******************************************************************************/ static CDFstatus DeleteRecords_r_64 (CDF, Var, firstVXRoffset, firstRec, lastRec, deletedTo, total) struct CDFstruct *CDF; struct VarStruct *Var; OFF_T firstVXRoffset; Int32 firstRec; Int32 lastRec; Int32 *deletedTo; Logical *total; { CDFstatus pStatus = CDF_OK; OFF_T vxrOffset = firstVXRoffset; struct VXRstruct64 VXR; int entryN; /**************************************************************************** * While another VXR... ****************************************************************************/ while (vxrOffset != (OFF_T) ZERO_OFFSET64) { /************************************************************************** * Read the VXR. **************************************************************************/ if (!sX(ReadVXR64(CDF->fp,vxrOffset, VXR_RECORD,&VXR, VXR_NULL),&pStatus)) return pStatus; /************************************************************************** * For each VXR entry... **************************************************************************/ for (entryN = 0; entryN < VXR.NusedEntries; entryN++) { /*********************************************************************** * If some of the records to be deleted are within this entry... ***********************************************************************/ if (!(lastRec < VXR.First[entryN] || firstRec > VXR.Last[entryN])) { Int32 first = MAXIMUM(firstRec,VXR.First[entryN]); Int32 last = MINIMUM(lastRec,VXR.Last[entryN]); Int32 irType; /********************************************************************* * Determine the type of internal record pointed to by this entry. *********************************************************************/ if (!sX(ReadIrType64(CDF->fp, VXR.Offset[entryN], &irType),&pStatus)) return pStatus; /********************************************************************* * Based on the type of internal record... *********************************************************************/ switch (irType) { /******************************************************************* * Another VXR (in a branch at a lower level)... *******************************************************************/ case VXR_: { Logical totalBelow = FALSE; /***************************************************************** * Recursively call this routine... *****************************************************************/ if (!sX(DeleteRecords_r_64(CDF,Var,VXR.Offset[entryN], first,last,deletedTo, &totalBelow),&pStatus)) return pStatus; /***************************************************************** * If the branch of VXRs below has not been totally deleted, update * this entry for the records that remain and return. *****************************************************************/ if (!totalBelow) { struct VXRstruct64 VXRbelow; if (!sX(ReadVXR64(CDF->fp,VXR.Offset[entryN], VXR_RECORD,&VXRbelow, VXR_NULL),&pStatus)) return pStatus; VXR.First[entryN] = VXRbelow.First[0]; while (VXRbelow.VXRnext != (OFF_T) ZERO_OFFSET64) { if (!sX(ReadVXR64(CDF->fp,VXRbelow.VXRnext, VXR_RECORD,&VXRbelow, VXR_NULL),&pStatus)) return pStatus; } VXR.Last[entryN] = VXRbelow.Last[(int)VXRbelow.NusedEntries-1]; if (!sX(WriteVXR64(CDF->fp,vxrOffset, VXR_RECORD,&VXR, VXR_NULL),&pStatus)) return pStatus; return pStatus; } /***************************************************************** * The branch of VXRs below has been totally deleted. Delete this * entry by moving the following entries up. If this is the last * entry, indicate to the caller that this branch has been totally * deleted. *****************************************************************/ if (!sX(DeleteVXRentry64(CDF,firstVXRoffset, vxrOffset,entryN,total),&pStatus)) return pStatus; return pStatus; } /******************************************************************* * A VVR or CVVR... *******************************************************************/ case VVR_: case CVVR_: { OFF_T irSize; /***************************************************************** * Read the size of the CVVR/VVR. *****************************************************************/ if (!sX(ReadIrSize64(CDF->fp, VXR.Offset[entryN], &irSize),&pStatus)) return pStatus; /***************************************************************** * Based on which records in the CVVR/VVR are being deleted... *****************************************************************/ if (first > VXR.First[entryN]) { if (last < VXR.Last[entryN]) { if (!sX(DeleteFromMiddle64(CDF,Var,first,last, vxrOffset,&VXR, entryN,irSize),&pStatus)) return pStatus; } else { if (!sX(DeleteFromEnd64(CDF,Var,first, vxrOffset,&VXR, entryN,irSize),&pStatus)) return pStatus; } } else { if (last < VXR.Last[entryN]) { if (!sX(DeleteFromFront64(CDF,Var,last, vxrOffset,&VXR, entryN,irSize),&pStatus)) return pStatus; } else { /************************************************************* * The entire block of records (ie. the entire CVVR/VVR) is * being deleted. *************************************************************/ if (!sX(WasteIR64(CDF,VXR.Offset[entryN], irSize),&pStatus)) return pStatus; if (!sX(DeleteVXRentry64(CDF,firstVXRoffset, vxrOffset, entryN,total),&pStatus)) return pStatus; } } *deletedTo = last; return pStatus; } /******************************************************************* * Something else - this is bad. *******************************************************************/ default: return CORRUPTED_V3_CDF; } } } /************************************************************************** * On to the next VXR... **************************************************************************/ vxrOffset = VXR.VXRnext; } /**************************************************************************** * The records to be deleted do not exist... ****************************************************************************/ *deletedTo = lastRec; return pStatus; } /****************************************************************************** * DeleteFromFront. ******************************************************************************/ static CDFstatus DeleteFromFront64 (CDF, Var, last, vxrOffset, VXR, entryN, irSize) struct CDFstruct *CDF; struct VarStruct *Var; Int32 last; OFF_T vxrOffset; struct VXRstruct64 *VXR; int entryN; OFF_T irSize; { CDFstatus pStatus = CDF_OK; switch (Var->vType) { case STANDARD_: case SPARSE_RECORDS_: { Int32 nDeleteRecords; OFF_T nRemainingBytes; Int32 nDeleteBytes, nRecords2, nBytes2; OFF_T deleteOffset, offset2, recordSize; /************************************************************************ * The records being deleted are at the beginning of the VVR. First * calculate needed offsets and sizes. ************************************************************************/ deleteOffset = VXR->Offset[entryN] + VVR_BASE_SIZE64; nDeleteRecords = last - VXR->First[entryN] + 1; nDeleteBytes = nDeleteRecords * Var->NphyRecBytes; nRecords2 = VXR->Last[entryN] - last; nBytes2 = nRecords2 * Var->NphyRecBytes; offset2 = VXR->Offset[entryN] + VVR_BASE_SIZE64 + nDeleteBytes; nRemainingBytes = irSize - VVR_BASE_SIZE64 - nBytes2; /************************************************************************ * Slide the remaining records to the beginning of the VVR. ************************************************************************/ if (!sX(CopyBytes64(CDF->fp,offset2, CDF_READ_ERROR, nBytes2,CDF->fp, deleteOffset, CDF_WRITE_ERROR),&pStatus)) return pStatus; /************************************************************************ * Update the VXR entry. ************************************************************************/ VXR->First[entryN] = last + 1; if (!sX(WriteVXR64(CDF->fp,vxrOffset, VXR_RECORD,VXR, VXR_NULL),&pStatus)) return pStatus; /************************************************************************ * If possible, waste the unused bytes that are now at the end of the * VVR (and update the record size field). Otherwise, the record size * field of the VVR remains unchanged. ************************************************************************/ if (nRemainingBytes >= UIR_BASE_SIZE64) { OFF_T offset = deleteOffset + nBytes2; if (!sX(WasteIR64(CDF,offset, nRemainingBytes),&pStatus)) return pStatus; recordSize = VVR_BASE_SIZE64 + nBytes2; if (!sX(WriteVVR64(CDF->fp,VXR->Offset[entryN], VVR_RECORDSIZE,&recordSize, VVR_NULL),&pStatus)) return pStatus; } break; } case COMPRESSED_: case SPARSE_COMPRESSED_RECORDS_: { Int32 nRecords = VXR->Last[entryN] - VXR->First[entryN] + 1; OFF_T uSize = nRecords * Var->NphyRecBytes; Int32 firstRecord2, nRecords2; OFF_T cSize; OFF_T offset2, newOffset, nBytes2; /************************************************************************ * Initialize staging area and scratch space. ************************************************************************/ if (Var->stage.areaOffset64 == (OFF_T) NO_OFFSET64) { Int32 nBytes = Var->blockingFactor * Var->NphyRecBytes; if (!sX(InitVarStage64(CDF,Var,nBytes),&pStatus)) return pStatus; } if (!sX(InitScratch64(ScratchDirectory(CDF), &(CDF->compressFp), CDF->compressCacheSize),&pStatus)) return pStatus; /************************************************************************ * Bring the CVVR/VVR to the staging area. ************************************************************************/ if (!sX(DecompressToStage64(CDF,Var, VXR->Offset[entryN], uSize),&pStatus)) return pStatus; /************************************************************************ * Waste the CVVR/VVR. ************************************************************************/ if (!sX(WasteIR64(CDF,VXR->Offset[entryN],irSize),&pStatus)) return pStatus; /************************************************************************ * Calculate sizes/offsets for the block of remaining records. ************************************************************************/ firstRecord2 = last + 1; nRecords2 = VXR->Last[entryN] - last; if (nRecords2 <= 0) break; offset2 = Var->stage.areaOffset64 + (Var->NphyRecBytes * (firstRecord2 - VXR->First[entryN])); nBytes2 = nRecords2 * Var->NphyRecBytes; /************************************************************************ * Compress the block of remaining records... ************************************************************************/ if (!sX(Compress64(CDF->stage.fp,offset2, nBytes2,SCRATCH_READ_ERROR, Var->cType,Var->cParms, CDF->compressFp,(OFF_T) ZERO_OFFSET64, &cSize,SCRATCH_WRITE_ERROR),&pStatus)) return pStatus; /************************************************************************ * ...and allocate/write the CVVR/VVR. ************************************************************************/ if (!sX(WriteCVVRorVVR64(CDF,cSize,offset2, nBytes2,&newOffset),&pStatus)) return pStatus; /************************************************************************ * Update the index entry for the block of remaining records. ************************************************************************/ VXR->First[entryN] = firstRecord2; VXR->Offset[entryN] = newOffset; if (!sX(WriteVXR64(CDF->fp,vxrOffset, VXR_RECORD,VXR, VXR_NULL),&pStatus)) return pStatus; break; } default: return CDF_INTERNAL_ERROR; } return pStatus; } /****************************************************************************** * DeleteFromMiddle64. ******************************************************************************/ static CDFstatus DeleteFromMiddle64 (CDF, Var, first, last, vxrOffset, VXR, entryN, irSize) struct CDFstruct *CDF; struct VarStruct *Var; Int32 first; Int32 last; OFF_T vxrOffset; struct VXRstruct64 *VXR; int entryN; OFF_T irSize; { CDFstatus pStatus = CDF_OK; switch (Var->vType) { case STANDARD_: case SPARSE_RECORDS_: { Int32 nRecords1, nBytes1, nDeleteRecords; Int32 nDeleteBytes, firstRecord2, lastRecord2, nRecords2; Int32 nBytes2, nExtraBytes, vvr_ = VVR_; Int32 nRemainingBytes; OFF_T deleteOffset, offset2, vvrOffset, recordSize; /************************************************************************ * A block of records will remain at the beginning and at the end. First * calculate needed offsets and sizes. Note that the number of bytes in * the second remaining block of records takes into account any extra * bytes that may exist at the end of the VVR. ************************************************************************/ nRecords1 = first - VXR->First[entryN]; nBytes1 = nRecords1 * Var->NphyRecBytes; deleteOffset = VXR->Offset[entryN] + VVR_BASE_SIZE64 + nBytes1; nDeleteRecords = last - first + 1; nDeleteBytes = nDeleteRecords * Var->NphyRecBytes; firstRecord2 = last + 1; lastRecord2 = VXR->Last[entryN]; nRecords2 = lastRecord2 - firstRecord2 + 1; offset2 = deleteOffset + nDeleteBytes; nBytes2 = nRecords2 * Var->NphyRecBytes; nExtraBytes = (Int32) (irSize - VVR_BASE_SIZE64 - nBytes1 - nDeleteBytes - nBytes2); /************************************************************************ * If the second block of remaining records cannot remain in the same * place... ************************************************************************/ if (nDeleteBytes < VVR_BASE_SIZE64) { /********************************************************************** * Move the second block of remaining records to a new VVR. **********************************************************************/ recordSize = VVR_BASE_SIZE64 + nBytes2; if (!sX(AllocateIR64(CDF,recordSize,&vvrOffset),&pStatus)) return pStatus; if (!sX(WriteVVR64(CDF->fp,vvrOffset, VVR_RECORDSIZE,&recordSize, VVR_RECORDTYPE,&vvr_, VVR_NULL),&pStatus)) return pStatus; if (!sX(CopyBytes64(CDF->fp,offset2, CDF_READ_ERROR, nBytes2,CDF->fp, (vvrOffset + VVR_BASE_SIZE64), CDF_WRITE_ERROR),&pStatus)) return pStatus; /********************************************************************** * If the remaining bytes can be changed to a UIR... **********************************************************************/ nRemainingBytes = nDeleteBytes + nBytes2 + nExtraBytes; if (nRemainingBytes >= UIR_BASE_SIZE64) { recordSize = VVR_BASE_SIZE64 + nBytes1; if (!sX(WriteVVR64(CDF->fp,VXR->Offset[entryN], VVR_RECORDSIZE,&recordSize, VVR_NULL),&pStatus)) return pStatus; if (!sX(WasteIR64(CDF,deleteOffset, nRemainingBytes),&pStatus)) return pStatus; } /********************************************************************** * Update the VXR entry for the first block of remaining records. **********************************************************************/ VXR->Last[entryN] = first - 1; if (!sX(WriteVXR64(CDF->fp,vxrOffset, VXR_RECORD,VXR, VXR_NULL),&pStatus)) return pStatus; /********************************************************************** * Insert a VXR entry for the new VVR created for the second block of * remaining records. **********************************************************************/ if (!sX(InsertIndexEntry64(CDF,vxrOffset, entryN,(Logical)TRUE, firstRecord2,lastRecord2, vvrOffset),&pStatus)) return pStatus; } else { /********************************************************************** * Update record size field of VVR for the first block of remaining * records and create a UIR for the bytes being "deleted" that are not * going to be used for the new VVR containing the second block of * remaining records. **********************************************************************/ nRemainingBytes = nDeleteBytes - VVR_BASE_SIZE64; if (nRemainingBytes < UIR_BASE_SIZE64) recordSize = VVR_BASE_SIZE64 + nBytes1 + nRemainingBytes; else { recordSize = VVR_BASE_SIZE64 + nBytes1; if (!sX(WasteIR64(CDF,deleteOffset, nRemainingBytes),&pStatus)) return pStatus; } if (!sX(WriteVVR64(CDF->fp,VXR->Offset[entryN], VVR_RECORDSIZE,&recordSize, VVR_NULL),&pStatus)) return pStatus; /********************************************************************** * Update the VXR entry for the first block of remaining records. **********************************************************************/ VXR->Last[entryN] = first - 1; if (!sX(WriteVXR64(CDF->fp,vxrOffset, VXR_RECORD,VXR, VXR_NULL),&pStatus)) return pStatus; /********************************************************************** * Write the record size and type fields of the new VVR for the second * block of remaining records. **********************************************************************/ vvrOffset = offset2 - VVR_BASE_SIZE64; recordSize = VVR_BASE_SIZE64 + nBytes2 + nExtraBytes; if (!sX(WriteVVR64(CDF->fp,vvrOffset, VVR_RECORDSIZE,&recordSize, VVR_RECORDTYPE,&vvr_, VVR_NULL),&pStatus)) return pStatus; /********************************************************************** * Insert a VXR entry for the new VVR created for the second block of * remaining records. **********************************************************************/ if (!sX(InsertIndexEntry64(CDF,vxrOffset, entryN,(Logical)TRUE, firstRecord2,lastRecord2, vvrOffset),&pStatus)) return pStatus; } break; } case COMPRESSED_: case SPARSE_COMPRESSED_RECORDS_: { Int32 nRecords = VXR->Last[entryN] - VXR->First[entryN] + 1; OFF_T uSize = nRecords * Var->NphyRecBytes; Int32 nRecords1, firstRecord2, lastRecord2, nRecords2; OFF_T offset2, nBytes1, nBytes2, cSize, newOffset; /************************************************************************ * Initialize staging area and scratch space. ************************************************************************/ if (Var->stage.areaOffset64 == (OFF_T) NO_OFFSET64) { Int32 nBytes = Var->blockingFactor * Var->NphyRecBytes; if (!sX(InitVarStage64(CDF,Var,nBytes),&pStatus)) return pStatus; } if (!sX(InitScratch64(ScratchDirectory(CDF), &(CDF->compressFp), CDF->compressCacheSize),&pStatus)) return pStatus; /************************************************************************ * Bring the CVVR/VVR to the staging area. ************************************************************************/ if (!sX(DecompressToStage64(CDF,Var, VXR->Offset[entryN], uSize),&pStatus)) return pStatus; /************************************************************************ * Waste the CVVR/VVR. ************************************************************************/ if (!sX(WasteIR64(CDF,VXR->Offset[entryN],irSize),&pStatus)) return pStatus; /************************************************************************ * Calculate sizes/offsets for the first and second blocks of remaining * records. ************************************************************************/ nRecords1 = first - VXR->First[entryN]; nBytes1 = nRecords1 * Var->NphyRecBytes; firstRecord2 = last + 1; lastRecord2 = VXR->Last[entryN]; nRecords2 = lastRecord2 - firstRecord2 + 1; offset2 = Var->stage.areaOffset64 + (Var->NphyRecBytes * (firstRecord2 - VXR->First[entryN])); nBytes2 = nRecords2 * Var->NphyRecBytes; /************************************************************************ * Compress the first block of remaining records... ************************************************************************/ if (!sX(Compress64(CDF->stage.fp, Var->stage.areaOffset64, nBytes1,SCRATCH_READ_ERROR, Var->cType,Var->cParms, CDF->compressFp,(OFF_T) ZERO_OFFSET64, &cSize,SCRATCH_WRITE_ERROR),&pStatus)) return pStatus; /************************************************************************ * ...and allocate/write the CVVR/VVR. ************************************************************************/ if (!sX(WriteCVVRorVVR64(CDF,cSize, Var->stage.areaOffset64, nBytes1,&newOffset),&pStatus)) return pStatus; /************************************************************************ * Update the index entry for the first block of remaining records. ************************************************************************/ VXR->Last[entryN] = first - 1; VXR->Offset[entryN] = newOffset; if (!sX(WriteVXR64(CDF->fp,vxrOffset, VXR_RECORD,VXR, VXR_NULL),&pStatus)) return pStatus; /************************************************************************ * Compress the second block of remaining records... ************************************************************************/ if (!sX(Compress64(CDF->stage.fp,offset2, nBytes2,SCRATCH_READ_ERROR, Var->cType,Var->cParms, CDF->compressFp,(OFF_T) ZERO_OFFSET64, &cSize,SCRATCH_WRITE_ERROR),&pStatus)) return pStatus; /************************************************************************ * ...and allocate/write the CVVR/VVR. ************************************************************************/ if (!sX(WriteCVVRorVVR64(CDF,cSize,offset2, nBytes2,&newOffset),&pStatus)) return pStatus; /************************************************************************ * Insert a new index entry for the second block of remaining records. ************************************************************************/ if (!sX(InsertIndexEntry64(CDF,vxrOffset, entryN,(Logical)TRUE, firstRecord2,lastRecord2, newOffset),&pStatus)) return pStatus; break; } default: return CDF_INTERNAL_ERROR; } return pStatus; } /****************************************************************************** * DeleteFromEnd64. ******************************************************************************/ static CDFstatus DeleteFromEnd64 (CDF, Var, first, vxrOffset, VXR, entryN, irSize) struct CDFstruct *CDF; struct VarStruct *Var; Int32 first; OFF_T vxrOffset; struct VXRstruct64 *VXR; int entryN; OFF_T irSize; { CDFstatus pStatus = CDF_OK; switch (Var->vType) { case STANDARD_: case SPARSE_RECORDS_: { Int32 nRecords1, nBytes1; OFF_T nRemainingBytes, deleteOffset, recordSize; /************************************************************************ * First calculate needed offsets and sizes. ************************************************************************/ nRecords1 = first - VXR->First[entryN]; nBytes1 = nRecords1 * Var->NphyRecBytes; deleteOffset = VXR->Offset[entryN] + VVR_BASE_SIZE64 + nBytes1; nRemainingBytes = irSize - VVR_BASE_SIZE64 - nBytes1; /************************************************************************ * Update the VXR entry. ************************************************************************/ VXR->Last[entryN] = first - 1; if (!sX(WriteVXR64(CDF->fp,vxrOffset, VXR_RECORD,VXR, VXR_NULL),&pStatus)) return pStatus; /************************************************************************ * If enough bytes are being deleted for a UIR, waste them and update * the record size field of the VVR. ************************************************************************/ if (nRemainingBytes >= UIR_BASE_SIZE64) { if (!sX(WasteIR64(CDF,deleteOffset, nRemainingBytes),&pStatus)) return pStatus; recordSize = VVR_BASE_SIZE64 + nBytes1; if (!sX(WriteVVR64(CDF->fp,VXR->Offset[entryN], VVR_RECORDSIZE,&recordSize, VVR_NULL),&pStatus)) return pStatus; } break; } case COMPRESSED_: case SPARSE_COMPRESSED_RECORDS_: { Int32 nRecords = VXR->Last[entryN] - VXR->First[entryN] + 1; OFF_T uSize = nRecords * Var->NphyRecBytes; Int32 nRecords1; OFF_T nBytes1, cSize; OFF_T newOffset; /************************************************************************ * Initialize staging area and scratch space. ************************************************************************/ if (Var->stage.areaOffset64 == (OFF_T) NO_OFFSET64) { Int32 nBytes = Var->blockingFactor * Var->NphyRecBytes; if (!sX(InitVarStage64(CDF,Var,nBytes),&pStatus)) return pStatus; } if (!sX(InitScratch64(ScratchDirectory(CDF), &(CDF->compressFp), CDF->compressCacheSize),&pStatus)) return pStatus; /************************************************************************ * Bring the CVVR/VVR to the staging area. ************************************************************************/ if (!sX(DecompressToStage64(CDF,Var, VXR->Offset[entryN], uSize),&pStatus)) return pStatus; /************************************************************************ * Waste the CVVR/VVR. ************************************************************************/ if (!sX(WasteIR64(CDF,VXR->Offset[entryN],irSize),&pStatus)) return pStatus; /************************************************************************ * Calculate sizes/offsets for the block of remaining records. ************************************************************************/ nRecords1 = first - VXR->First[entryN]; nBytes1 = nRecords1 * Var->NphyRecBytes; /************************************************************************ * Compress the block of remaining records... ************************************************************************/ if (!sX(Compress64(CDF->stage.fp, Var->stage.areaOffset64, nBytes1,SCRATCH_READ_ERROR, Var->cType,Var->cParms, CDF->compressFp,(OFF_T) ZERO_OFFSET64, &cSize,SCRATCH_WRITE_ERROR),&pStatus)) return pStatus; /************************************************************************ * ...and allocate/write the CVVR/VVR. ************************************************************************/ if (!sX(WriteCVVRorVVR64(CDF,cSize, Var->stage.areaOffset64, nBytes1,&newOffset),&pStatus)) return pStatus; /************************************************************************ * Update the index entry for the block of remaining records. ************************************************************************/ VXR->Last[entryN] = first - 1; VXR->Offset[entryN] = newOffset; if (!sX(WriteVXR64(CDF->fp,vxrOffset, VXR_RECORD,VXR, VXR_NULL),&pStatus)) return pStatus; break; } default: return CDF_INTERNAL_ERROR; } return pStatus; } /****************************************************************************** * DeleteVXRentry64. ******************************************************************************/ static CDFstatus DeleteVXRentry64 (CDF, firstVXRoffset, delVXRoffset, delEntryN, total) struct CDFstruct *CDF; OFF_T firstVXRoffset; OFF_T delVXRoffset; int delEntryN; Logical *total; { CDFstatus pStatus = CDF_OK; OFF_T vxrOffset = firstVXRoffset, prevVXRoffset = (OFF_T) ZERO_OFFSET64; struct VXRstruct64 VXR, nextVXR; int entryN, lastEntryN; /**************************************************************************** * Find the VXR in which an entry is being deleted while keeping track of the * previous VXR. ****************************************************************************/ if (!sX(ReadVXR64(CDF->fp,vxrOffset, VXR_RECORD,&VXR, VXR_NULL),&pStatus)) return pStatus; while (vxrOffset != delVXRoffset) { prevVXRoffset = vxrOffset; vxrOffset = VXR.VXRnext; if (!sX(ReadVXR64(CDF->fp,vxrOffset, VXR_RECORD,&VXR, VXR_NULL),&pStatus)) return pStatus; } /**************************************************************************** * Until done... ****************************************************************************/ for (;;) { /************************************************************************* * Move the following entries up. Nothing will happen if there is only * one entry. *************************************************************************/ for (entryN = delEntryN + 1; entryN < VXR.NusedEntries; entryN++) { VXR.First[entryN-1] = VXR.First[entryN]; VXR.Last[entryN-1] = VXR.Last[entryN]; VXR.Offset[entryN-1] = VXR.Offset[entryN]; } lastEntryN = (int) (VXR.NusedEntries - 1); /************************************************************************* * If a VXR does not follow, erase the last entry if there was more than * one or waste the VXR is there was only one (entry). *************************************************************************/ if (VXR.VXRnext == (OFF_T) ZERO_OFFSET64) { if (VXR.NusedEntries > 1) { VXR.First[lastEntryN] = NO_RECORD; VXR.Last[lastEntryN] = NO_RECORD; VXR.Offset[lastEntryN] = (OFF_T) NO_OFFSET64; VXR.NusedEntries--; if (!sX(WriteVXR64(CDF->fp,vxrOffset, VXR_RECORD,&VXR, VXR_NULL),&pStatus)) return pStatus; } else { if (!sX(WasteIR64(CDF,vxrOffset, VXR.RecordSize),&pStatus)) return pStatus; if (prevVXRoffset != (OFF_T) ZERO_OFFSET64) { OFF_T zeroOffset = (OFF_T) ZERO_OFFSET64; if (!sX(WriteVXR64(CDF->fp,prevVXRoffset, VXR_VXRNEXT,&zeroOffset, VXR_NULL),&pStatus)) return pStatus; } else *total = TRUE; } return pStatus; } /************************************************************************* * Otherwise, read the next VXR, set the current VXR's last entry to the * first entry of the next VXR, rewrite the current VXR, and then set the * current VXR to the next VXR and set the first entry to be deleted and * continue... *************************************************************************/ if (!sX(ReadVXR64(CDF->fp,VXR.VXRnext, VXR_RECORD,&nextVXR, VXR_NULL),&pStatus)) return pStatus; VXR.First[lastEntryN] = nextVXR.First[0]; VXR.Last[lastEntryN] = nextVXR.Last[0]; VXR.Offset[lastEntryN] = nextVXR.Offset[0]; if (!sX(WriteVXR64(CDF->fp,vxrOffset, VXR_RECORD,&VXR, VXR_NULL),&pStatus)) return pStatus; prevVXRoffset = vxrOffset; vxrOffset = VXR.VXRnext; VXR = nextVXR; delEntryN = 0; } } /****************************************************************************** * InsertIndexEntry64. ******************************************************************************/ static CDFstatus InsertIndexEntry64 (CDF, vxrOffset, entryN, after, first, last, offset) struct CDFstruct *CDF; OFF_T vxrOffset; int entryN; Logical after; /* TRUE: Insert the new entry after `entryN'. FALSE: Insert the new entry at `entryN'. */ Int32 first; Int32 last; OFF_T offset; { CDFstatus pStatus = CDF_OK; struct VXRstruct64 VXR; int eN, lastEntryN; Int32 pushedFirst, pushedLast; OFF_T pushedOffset, newVXRoffset; /**************************************************************************** * Read the VXR. ****************************************************************************/ if (!sX(ReadVXR64(CDF->fp,vxrOffset, VXR_RECORD,&VXR, VXR_NULL),&pStatus)) return pStatus; /**************************************************************************** * If there is room in this VXR for another entry, simply insert it. ****************************************************************************/ if (VXR.NusedEntries < VXR.Nentries) { if (after) { for (eN = (int) VXR.NusedEntries; eN > entryN + 1; eN--) { VXR.First[eN] = VXR.First[eN-1]; VXR.Last[eN] = VXR.Last[eN-1]; VXR.Offset[eN] = VXR.Offset[eN-1]; } VXR.First[entryN+1] = first; VXR.Last[entryN+1] = last; VXR.Offset[entryN+1] = offset; } else { for (eN = (int) VXR.NusedEntries; eN > entryN; eN--) { VXR.First[eN] = VXR.First[eN-1]; VXR.Last[eN] = VXR.Last[eN-1]; VXR.Offset[eN] = VXR.Offset[eN-1]; } VXR.First[entryN] = first; VXR.Last[entryN] = last; VXR.Offset[entryN] = offset; } VXR.NusedEntries++; if (!sX(WriteVXR64(CDF->fp,vxrOffset, VXR_RECORD,&VXR, VXR_NULL),&pStatus)) return pStatus; return pStatus; } /**************************************************************************** * No room for another entry... ****************************************************************************/ lastEntryN = (int) (VXR.NusedEntries - 1); if (after) { if (entryN == lastEntryN) { pushedFirst = first; pushedLast = last; pushedOffset = offset; } else { pushedFirst = VXR.First[lastEntryN]; pushedLast = VXR.Last[lastEntryN]; pushedOffset = VXR.Offset[lastEntryN]; for (eN = lastEntryN; eN > entryN + 1; eN--) { VXR.First[eN] = VXR.First[eN-1]; VXR.Last[eN] = VXR.Last[eN-1]; VXR.Offset[eN] = VXR.Offset[eN-1]; } VXR.First[entryN+1] = first; VXR.Last[entryN+1] = last; VXR.Offset[entryN+1] = offset; } } else { pushedFirst = VXR.First[lastEntryN]; pushedLast = VXR.Last[lastEntryN]; pushedOffset = VXR.Offset[lastEntryN]; for (eN = lastEntryN; eN > entryN; eN--) { VXR.First[eN] = VXR.First[eN-1]; VXR.Last[eN] = VXR.Last[eN-1]; VXR.Offset[eN] = VXR.Offset[eN-1]; } VXR.First[entryN] = first; VXR.Last[entryN] = last; VXR.Offset[entryN] = offset; } /**************************************************************************** * If this is the last VXR on the linked list, allocate a new VXR, update * this VXR with the new VXR's offset, and write the new VXR. ****************************************************************************/ if (VXR.VXRnext == (OFF_T) ZERO_OFFSET64) { if (!sX(AllocateIR64(CDF,(Int32)VXR_BASE_SIZE64, &newVXRoffset),&pStatus)) return pStatus; VXR.VXRnext = newVXRoffset; if (!sX(WriteVXR64(CDF->fp,vxrOffset, VXR_RECORD,&VXR, VXR_NULL),&pStatus)) return pStatus; InitNewVXR64 (&VXR, pushedFirst, pushedLast, pushedOffset); if (!sX(WriteVXR64(CDF->fp,newVXRoffset, VXR_RECORD,&VXR, VXR_NULL),&pStatus)) return pStatus; return pStatus; } /**************************************************************************** * There is another VXR on the linked list - update this VXR and recursively * call this routine to insert the entry that was pushed out in the first * entry position. ****************************************************************************/ if (!sX(WriteVXR64(CDF->fp,vxrOffset, VXR_RECORD,&VXR, VXR_NULL),&pStatus)) return pStatus; if (!sX(InsertIndexEntry64(CDF,VXR.VXRnext, 0,(Logical)FALSE, pushedFirst,pushedLast, pushedOffset),&pStatus)) return pStatus; return pStatus; } /****************************************************************************** * UpdateIndexEntries_r_64. ******************************************************************************/ static CDFstatus UpdateIndexEntries_r_64 (fp, vxrOffset, aboveRecord, recordCount) vFILE *fp; OFF_T vxrOffset; Int32 aboveRecord; Int32 recordCount; { CDFstatus pStatus = CDF_OK; struct VXRstruct64 VXR; int entryN; Int32 irType; while (vxrOffset != (OFF_T) ZERO_OFFSET64) { Logical modified = FALSE; if (!sX(ReadVXR64(fp,vxrOffset, VXR_RECORD,&VXR, VXR_NULL),&pStatus)) return pStatus; for (entryN = 0; entryN < VXR.NusedEntries; entryN++) { if (VXR.Last[entryN] > aboveRecord) { if (!sX(ReadIrType64(fp,VXR.Offset[entryN], &irType),&pStatus)) return pStatus; switch (irType) { case VXR_: if (!sX(UpdateIndexEntries_r_64(fp,VXR.Offset[entryN], aboveRecord, recordCount),&pStatus)) return pStatus; break; case VVR_: case CVVR_: break; default: return CORRUPTED_V3_CDF; } if (VXR.First[entryN] > aboveRecord) VXR.First[entryN] -= recordCount; VXR.Last[entryN] -= recordCount; modified = TRUE; } } if (modified) { if (!sX(WriteVXR64(fp,vxrOffset, VXR_RECORD,&VXR, VXR_NULL),&pStatus)) return pStatus; } vxrOffset = VXR.VXRnext; } return pStatus; } /****************************************************************************** * WriteCVVRorVVR64. ******************************************************************************/ static CDFstatus WriteCVVRorVVR64 (CDF, cSize, stageOffset, uSize, newOffset) struct CDFstruct *CDF; OFF_T cSize; OFF_T stageOffset; OFF_T uSize; OFF_T *newOffset; { CDFstatus pStatus = CDF_OK; OFF_T recordSize; OFF_T tOffset; if (CVVR_BASE_SIZE64 + cSize < VVR_BASE_SIZE64 + uSize) { struct CVVRstruct64 CVVR; recordSize = CVVR_BASE_SIZE64 + cSize; LoadCVVRx64 (CVVR, recordSize, cSize) if (!sX(AllocateIR64(CDF,recordSize,newOffset),&pStatus)) return pStatus; if (!sX(WriteCVVR64(CDF->fp,*newOffset, CVVR_RECORDx,&CVVR, CVVR_NULL),&pStatus)) return pStatus; tOffset = *newOffset + CVVR_BASE_SIZE64; if (!sX(CopyBytes64(CDF->compressFp,(OFF_T) ZERO_OFFSET64, SCRATCH_READ_ERROR,cSize,CDF->fp, tOffset,CDF_WRITE_ERROR),&pStatus)) return pStatus; } else { struct VVRstruct64 VVR; recordSize = VVR_BASE_SIZE64 + uSize; LoadVVRx64 (VVR, recordSize) if (!sX(AllocateIR64(CDF,recordSize,newOffset),&pStatus)) return pStatus; if (!sX(WriteVVR64(CDF->fp,*newOffset, VVR_RECORDx,&VVR, VVR_NULL),&pStatus)) return pStatus; tOffset = *newOffset + VVR_BASE_SIZE64; if (!sX(CopyBytes64(CDF->stage.fp,stageOffset, SCRATCH_READ_ERROR,uSize,CDF->fp, tOffset,CDF_WRITE_ERROR),&pStatus)) return pStatus; } return pStatus; }