/******************************************************************************
*
* NSSDC/CDF CDF `close' operations.
*
* Version 1.5a, 21-Feb-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 7-Dec-93, J Love CDF V2.4. Added zMode.
* V1.3 15-Nov-94, J Love CDF V2.5.
* V1.3a 24-Feb-95, J Love Solaris 2.3 IDL i/f.
* V1.4 20-Jul-95, J Love CDFexport-related changes.
* V1.5 8-Aug-96, J Love CDF V2.6.
* V1.4a 21-Feb-97, J Love Removed RICE.
* V2.0 08-Apr-04, M Liu Replaced VSTREAM.STATS with VSTREAM_STATS.
* Removed call to LocateCurrentVar when r/zVAR_
* is closed as it does more than needed.
*
******************************************************************************/
#include "cdflib.h"
/******************************************************************************
* CDFclo.
******************************************************************************/
STATICforIDL CDFstatus CDFclo (Va, Cur)
struct VAstruct *Va;
struct CurStruct *Cur;
{
CDFstatus pStatus = CDF_OK;
switch (Va->item) {
/**************************************************************************
* CDF_
* Close a CDF with or without statistics for the dotCDF file.
**************************************************************************/
case CDF_:
case CDFwithSTATS_: {
struct CDFstruct *CDF; vSTATS vStats;
Logical statistics = (Va->item == CDFwithSTATS_);
vSTATS *vStatsDotP = BOO(statistics,va_arg(Va->ap,vSTATS *),NULL);
vSTATS *vStatsStageP = BOO(statistics,va_arg(Va->ap,vSTATS *),NULL);
vSTATS *vStatsCompressP = BOO(statistics,va_arg(Va->ap,vSTATS *),NULL);
/************************************************************************
* Initialize the Vstream statistics.
************************************************************************/
AddTOvStats (vStatsDotP, NULL);
AddTOvStats (vStatsStageP, NULL);
AddTOvStats (vStatsCompressP, NULL);
/************************************************************************
* Validate the current CDF. Don't use `SelectCDF' here because we don't
* want to return NO_MORE_ACCESS if that is the case.
************************************************************************/
if (Cur->cdf == NULL)
return NO_CDF_SELECTED;
else
CDF = Cur->cdf;
/************************************************************************
* If this is a CDF for which access was aborted, simply free the CDF's
* memory.
************************************************************************/
if (CDF->magic == ABORTEDid_MAGIC_NUMBER) {
KillAbortedCDF (CDF, Cur);
break;
}
/************************************************************************
* Get the Vstream statistics for the dotCDF file(s) so far.
************************************************************************/
AddTOvStats (vStatsDotP, &CDF->dotCDFvStats);
AddTOvStats (vStatsDotP, &CDF->uDotCDFvStats);
/************************************************************************
* If the CDF is open read/write, update the dotCDF file.
************************************************************************/
if (CDF->status == READ_WRITE) {
if (!sX(UpdateDotCDF(CDF),&pStatus)) {
AbortAccess (CDF, noUPDATE, noDELETE);
KillAbortedCDF (CDF, Cur);
return pStatus;
}
}
/************************************************************************
* If the CDF is compressed...
************************************************************************/
if (CDF->uDotFp != NULL) {
/**********************************************************************
* If the CDF is open read/write... The uncompressed dotCDF file will
* be flushed and the compressed dotCDF will be deleted and recreated
* from the uncompressed dotCDF file.
**********************************************************************/
if (CDF->status == READ_WRITE) {
char pathName[DU_MAX_PATH_LEN+1];
Int32 CPRoffset; struct CPRstruct CPR;
/********************************************************************
* First flush the uncompressed dotCDF file.
********************************************************************/
if (!FLUSHv(CDF->uDotFp)) {
AbortAccess (CDF, noUPDATE, noDELETE);
KillAbortedCDF (CDF, Cur);
return CDF_WRITE_ERROR;
}
/********************************************************************
* Read the compression parameters from the compressed dotCDF file.
********************************************************************/
if (!sX(ReadCCR(CDF->dotFp,V2_CCR_OFFSET,
CCR_CPROFFSET,&CPRoffset,
CCR_NULL),&pStatus)) {
AbortAccess (CDF, noUPDATE, noDELETE);
KillAbortedCDF (CDF, Cur);
return pStatus;
}
if (!sX(ReadCPR(CDF->dotFp,CPRoffset,
CPR_RECORD,&CPR,
CPR_NULL),&pStatus)) {
AbortAccess (CDF, noUPDATE, noDELETE);
KillAbortedCDF (CDF, Cur);
return pStatus;
}
/********************************************************************
* Delete the compressed dotCDF file.
********************************************************************/
if (!DELETEv(CDF->dotFp,&vStats)) {
CDF->dotFp = NULL;
AbortAccess (CDF, noUPDATE, noDELETE);
KillAbortedCDF (CDF, Cur);
return CDF_CLOSE_ERROR;
}
CDF->dotFp = NULL;
AddTOvStats (vStatsDotP, &vStats);
#if defined(DEBUG)
DisplayVs (getenv("VSTREAM_STATS"), "DotCDF..", &vStats);
#endif
/********************************************************************
* Recreate the compressed dotCDF file.
********************************************************************/
BuildFilePath (CDFt, CDF->CDFname, CDF->no_append,
CDF->upper_case_ext, CDF->version_numbers,
INT32_ZERO, pathName);
CDF->dotFp = V_open (pathName, WRITE_PLUS_a_mode);
if (CDF->dotFp == NULL) {
AbortAccess (CDF, noUPDATE, noDELETE);
KillAbortedCDF (CDF, Cur);
return CDF_CREATE_ERROR;
}
/********************************************************************
* Write the compressed dotCDF file.
********************************************************************/
if (!sX(WriteCompressedCDF(CDF,&CPR,notEMPTY),&pStatus)) {
AbortAccess (CDF, noUPDATE, noDELETE);
KillAbortedCDF (CDF, Cur);
return pStatus;
}
/********************************************************************
* Close the compressed dotCDF file.
********************************************************************/
if (!CLOSEv(CDF->dotFp,CDF,&vStats)) {
CDF->dotFp = NULL;
AbortAccess (CDF, noUPDATE, noDELETE);
KillAbortedCDF (CDF, Cur);
return CDF_CLOSE_ERROR;
}
CDF->dotFp = NULL;
AddTOvStats (vStatsDotP, &vStats);
#if defined(DEBUG)
DisplayVs (getenv("VSTREAM_STATS"), "DotCDF..", &vStats);
#endif
/********************************************************************
* Delete the uncompressed dotCDF file.
********************************************************************/
if (!DELETEv(CDF->uDotFp,&vStats)) {
CDF->uDotFp = NULL;
AbortAccess (CDF, noUPDATE, noDELETE);
KillAbortedCDF (CDF, Cur);
return CDF_CLOSE_ERROR;
}
CDF->uDotFp = NULL;
AddTOvStats (vStatsDotP, &vStats);
#if defined(DEBUG)
DisplayVs (getenv("VSTREAM_STATS"), "uDotCDF.", &vStats);
#endif
}
else {
/********************************************************************
* The CDF is open read/only. First close the compressed dotCDF file
* (which has not been changed).
********************************************************************/
if (!CLOSEv(CDF->dotFp,CDF,&vStats)) {
CDF->dotFp = NULL;
AbortAccess (CDF, noUPDATE, noDELETE);
KillAbortedCDF (CDF, Cur);
return CDF_CLOSE_ERROR;
}
CDF->dotFp = NULL;
AddTOvStats (vStatsDotP, &vStats);
#if defined(DEBUG)
DisplayVs (getenv("VSTREAM_STATS"), "DotCDF..", &vStats);
#endif
/********************************************************************
* Delete the uncompressed dotCDF file.
********************************************************************/
if (!DELETEv(CDF->uDotFp,&vStats)) {
CDF->uDotFp = NULL;
AbortAccess (CDF, noUPDATE, noDELETE);
KillAbortedCDF (CDF, Cur);
return CDF_CLOSE_ERROR;
}
CDF->uDotFp = NULL;
AddTOvStats (vStatsDotP, &vStats);
#if defined(DEBUG)
DisplayVs (getenv("VSTREAM_STATS"), "uDotCDF.", &vStats);
#endif
}
}
else {
/**********************************************************************
* Not compressed - first close the dotCDF file.
**********************************************************************/
if (!CLOSEv(CDF->dotFp,CDF,&vStats)) {
CDF->dotFp = NULL;
AbortAccess (CDF, noUPDATE, noDELETE);
KillAbortedCDF (CDF, Cur);
return CDF_CLOSE_ERROR;
}
CDF->dotFp = NULL;
AddTOvStats (vStatsDotP, &vStats);
#if defined(DEBUG)
DisplayVs (getenv("VSTREAM_STATS"), "DotCDF..", &vStats);
#endif
/**********************************************************************
* Close the variable files (if a multi-file CDF).
**********************************************************************/
if (!sX(CloseVarFiles(CDF),&pStatus)) {
AbortAccess (CDF, noUPDATE, noDELETE);
KillAbortedCDF (CDF, Cur);
return pStatus;
}
}
/************************************************************************
* Delete staging scratch file.
************************************************************************/
if (CDF->stage.fp != NULL) {
if (!DELETEv(CDF->stage.fp,&vStats)) {
CDF->stage.fp = NULL;
AbortAccess (CDF, noUPDATE, noDELETE);
KillAbortedCDF (CDF, Cur);
return SCRATCH_DELETE_ERROR;
}
CDF->stage.fp = NULL;
AddTOvStats (vStatsStageP, &vStats);
#if defined(DEBUG)
DisplayVs (getenv("VSTREAM_STATS"), "Stage...", &vStats);
#endif
}
/************************************************************************
* Delete compression scratch file.
************************************************************************/
if (CDF->compressFp != NULL) {
if (!DELETEv(CDF->compressFp,&vStats)) {
CDF->compressFp = NULL;
AbortAccess (CDF, noUPDATE, noDELETE);
KillAbortedCDF (CDF, Cur);
return SCRATCH_DELETE_ERROR;
}
CDF->compressFp = NULL;
AddTOvStats (vStatsCompressP, &vStats);
#if defined(DEBUG)
DisplayVs (getenv("VSTREAM_STATS"), "Compress", &vStats);
#endif
}
/************************************************************************
* Free memory used and clear current CDF.
************************************************************************/
FreeCDFid (CDF, FALSE);
Cur->cdf = NULL;
break;
}
/**************************************************************************
* rVAR_/zVAR_
* Close the current r/zVariable file.
**************************************************************************/
case rVAR_:
case zVAR_: {
Logical zOp = (Va->item == zVAR_);
struct CDFstruct *CDF; struct VarStruct *Var;
SelectCDF (Cur->cdf, CDF)
if (BADzOP(CDF,!zOp)) return ILLEGAL_IN_zMODE;
if (!CURRENTvarSELECTED(CDF,zOp)) return NO_VAR_SELECTED;
if (zModeON(CDF)) {
if (CDF->CURzVarNum < CDF->NrVars)
Var = CDF->rVars[(int)CDF->CURzVarNum];
else
Var = CDF->zVars[(int)(CDF->CURzVarNum - CDF->NrVars)];
} else
Var = BOO(zOp,CDF->zVars[(int)CDF->CURzVarNum],
CDF->rVars[(int)CDF->CURrVarNum]);
if (CDF->singleFile) {
sX (SINGLE_FILE_FORMAT, &pStatus);
break;
}
if (Var != NULL) {
if (Var->fp != NULL) {
if (!CLOSEv(Var->fp,NULL,NULL)) {
Var->fp = NULL;
AbortAccess (CDF, UPDATE, noDELETE);
return VAR_CLOSE_ERROR;
}
Var->fp = NULL;
}
else {
if (!sX(VAR_ALREADY_CLOSED,&pStatus)) return pStatus;
}
}
else {
if (!sX(VAR_ALREADY_CLOSED,&pStatus)) return pStatus;
}
break;
}
/**************************************************************************
* Unknown item, must be the next function.
**************************************************************************/
default: {
Va->fnc = Va->item;
break;
}
}
return pStatus;
}
syntax highlighted by Code2HTML, v. 0.9.1