/*===================================================================== * DD SYSTEM base package * DD_Server library * DD_GetData.c * V. 6.1 * author: Andrey Fedorov * * Last revision: * May 19 1997: Version 1.0 * 25 February 1999 by A.Grigoriev * DD_GetData was updated. V.2.0 * Methods of search in SetTime are changed. * April 12, 2002: NETCDF lib is changed V.3.0 * Oct 10, 2002 Communication prorocol is changed. V 4.0 * Oct 24, 2002 New calculation of thremaximum record size V. 4.1 * work with NC files is now in file ncfileop.c * May 7, 2003 : V 4.2 Cash work improoved (ncfileop.c also) * Jan 6, 2004: V 4.3 Error in ID closing is fixed * Jan 21, 2004: V.4.4 Error in free memory fixed, * Server can path several new files, and then return * Aug 12, 2004: V.4.5 New verbatim in the CLOSEID * Nov 18, 2004: V.4.6 Accomodation of new ncfileop.c * Mar 15, 2007 V.4.7 Fixed cash bag * Jul 10, 2007 V.5.0 According to Server protocol 4.5.1 * If "times" has "NODATA" string as name of the file, return "NOTIME" * New format of VI name (see DDGenProt.lyx) * Aug 02, 2007 V.5.1 Add WAITEXTCALL flag and LOCK file to GetData routines * Also global time limits * Sep 20, 2007 V.5.2 Refrech time limits after database update, database update after Get_Data call * Sep 23, 2007 V.5.3 Fedorov, New interface for SetTime() * Sep 24, 2007 V.5.4 Fedorov, Get_Data return is changed * Sep 25, 2007 V.5.5 Fedorov, Variable minimal gap * Feb 22, 2008, V.5.6 SetTime bug corrected -> nc_get,,,(...StartID...) not VarL->StartID !!!! * Mar 06, 2008, V.5.7 SetTime bug corrected -> * May 03, 2008, V.5.8 GlobalTime limits * May 06, 2008 V.5.9 Fedorov, Max Records number processing * May 15, 2008 V.5.10 Fedorov, NoData interval processing. Just go to the next correct data interval. * May 19, 2008 V.5.11 Fedorov, One record data interval. Time is interpreted as scalar * May 21, 2008 V.5.12 Fedorov, No data processing * Apr 11, 2009 V.5.13 Fedorov, Out of global limits * Apr 13, 2009 V.5.20 Fedorov, Reset of the pointer is in a spectal function * Apr 13, 2009 V.5.21 Fedorov, Set time between the last record and Stop time * Dec 8, 2012 V.6.0 Fedorov, New call to get the data structure, New multiparam call * Jan 11, 2013 V.6.1 Knizhnikova, Fedorov, SlobalStart check, If there is NOVAR, set the corresponding data constants to send the corresponding packet. *=====================================================================*/ #include #include "DD.h" #include "DD_comm.h" /*------------------ GLOBAL VARIABLES --------------------------*/ DD_Var_t **DD_Var ; /* Common for entire server session , all files */ size_t MaxIDNumber; /* The size of DD_Var array. Defined when new DD_Server session starts*/ extern int Verbose; extern LocalOrigSync(DD_Var_t *Local, DD_Var_t *Orig); /*#################################################################*/ /*----------------------- OpenInstr -------------------------------*/ /*#################################################################*/ /* * Open Virtual instrument by VInstrName and return ID. * Make entry point of DD_Var table * Fill General attributes fron the INFO file */ int OpenInstr(char *VInstrName) { char refname[PATHLENGTH]; /* full name of the reference file */ char *ddbase; /* Environment variable DDBASE (path to the DDBASE ROOT)*/ char RInstrName[MAXSETLENGTH]; /* Requested virtual instrument name */ int id; /* ID of open Virtual Instrument */ int refID,nameID; /* ID of reference file and Var in */ static size_t RefStart[2] = {0,0}; static size_t RefCount[2] = {4,PATHLENGTH}; static char RefVar[4][PATHLENGTH]; int len, status; char *VirInstrP; //Pointer to some part of virtual instrument unsigned UT[7]; // Buffer array to decode global time dd_tmstr_t *GTimeP; // Buffer structure to decode global time /** sleep(60); **/ if(Verbose) { fprintf(stderr,"OpenInstr(%s): begin\n",VInstrName); } /* Converting original name to the name in database */ strcpy(RInstrName,VInstrName); VirInstrP = (char *)RInstrName; while((VirInstrP = strchr(VirInstrP,':')) != NULL) *VirInstrP = '_'; /* Is this name in DD_Var structure ? */ for(id = 0; id < MaxIDNumber; id++) { if(DD_Var[id] != NULL) if(strcmp(RInstrName, DD_Var[id]->InstrName) == 0) { if(Verbose) fprintf(stderr,"OpenInstr(%s): VI is already open with ID = %d\n",VInstrName,id); return(id); } } if(Verbose) fprintf(stderr,"OpenInstr(%s): No such VI in DD_Var array. Create New Entry.\n",VInstrName); /* Is the empty space in DD_Var table */ id =0; while((DD_Var[id] != NULL) && (id < MaxIDNumber)) id++; if(id >= MaxIDNumber) { if(Verbose) fprintf(stderr,"OpenInstr(%s): No Room in DD_Var table\n",VInstrName); return(TOOMANYREQ); /* No room */ } /** if(Verbose) fprintf(stderr,"OpenInstr(%s): There is empty plase at %d\n",VInstrName,id); **/ /* Open reference NC file */ if((ddbase = getenv("DDBASE")) == NULL) return(NOREFFILE); strcpy(refname,ddbase); strcat(refname,REFNAME); status = nc_open(refname, NC_NOWRITE|NC_SHARE,&refID); if(status != NC_NOERR) { if(Verbose) fprintf(stderr,"OpentInstr(%s): open file %s, message: %s\n",VInstrName,refname,nc_strerror(status)); return(NOREFFILE); } status = nc_inq_varid(refID,RInstrName,&nameID); if(status != NC_NOERR) { if(Verbose) fprintf(stderr,"OpentInstr(%s): read %s, message: %s\n",VInstrName,RInstrName, nc_strerror(status)); return(NOVAR); } status = nc_get_vara_text(refID,nameID,RefStart,RefCount,(char *)RefVar); if(status != NC_NOERR) { if(Verbose) fprintf(stderr,"OpentInstr(%s): %s\n",VInstrName,nc_strerror(status)); return(NOVAR); } len = strcspn(RefVar[1]," "); RefVar[1][len] = '\0'; len = strcspn(RefVar[2]," "); RefVar[2][len] = '\0'; len = strcspn(RefVar[0]," "); RefVar[0][len] = '\0'; len = strcspn(RefVar[3]," "); RefVar[3][len] = '\0'; status = nc_close(refID); /* Create VI holder*/ DD_Var[id] = (DD_Var_t *)malloc(sizeof(DD_Var_t)); /* Init Values */ strcpy(DD_Var[id]->InstrName,RInstrName); DD_Var[id]->VarData = NULL; DD_Var[id]->ParamSize = 0; DD_Var[id]->AttrData.Dimensions = NULL; DD_Var[id]->AttrData.Variables = NULL; DD_Var[id]->ncID = -1; DD_Var[id]->Maxnc_rec = 0; DD_Var[id]->Cash.ID = -1; strcpy(DD_Var[id]->path, RefVar[0]); /*----- Init control Flags ---------------*/ DD_Var[id]->LastPacketFlag = OK; DD_Var[id]->NewFile = 0; DD_Var[id]->NewFileWasOpen = 0; /* ---------------------------------------------------------------- * Open and init "Times" file * -----------------------------------------------------------------*/ DD_Var[id]->VILocked = 0; DD_Var[id]->tmID = -1; strcpy(DD_Var[id]->TimesFileName,RefVar[1]); if((status = UpdateTimeInfo(DD_Var[id])) < 0) return status; /* ---------------------------------------------------------------- * Open "Info" file * -----------------------------------------------------------------*/ /* Attention: Constant information file open and close by request in GetAttribute() */ strcpy(DD_Var[id]->AttrName,RefVar[2]); DD_Var[id]->attrID = -1; /* * Important to make NULL all variables */ DD_Var[id]->AttrData.Dimensions = NULL; DD_Var[id]->AttrData.Variables = NULL; /** if(Verbose) fprintf(stderr,"OpentInstr(%s): ID = %d, Atributes are resetted\n",VInstrName,id); **/ /* ------------------------------------------------------------------- * Set cache file path */ strcpy(DD_Var[id]->Cash.CacheFilePath,RefVar[3]); /* ---------------------------------------------------------------- * Read Global timing and minimal gap from INFO file * -----------------------------------------------------------------*/ if((status = GetAttribute(id, GLOBSTARTNAME)) < 0) DD_Var[id]->GlobalStart = 0.0; else { sscanf((char *)((DD_Var[id]->AttrData).Variables[0]), ISOTIMEF, &UT[0],&UT[1],&UT[2],&UT[3],&UT[4],&UT[5],&UT[6]); SetDouble(GTimeP = UT2double(UT)); DD_Var[id]->GlobalStart = GTimeP->times; } if((status = GetAttribute(id, GLOBSTOPNAME)) < 0) DD_Var[id]->GlobalStop = 1.0e11; else { sscanf((char *)((DD_Var[id]->AttrData).Variables[0]), ISOTIMEF, &UT[0],&UT[1],&UT[2],&UT[3],&UT[4],&UT[5],&UT[6]); SetDouble(GTimeP = UT2double(UT)); DD_Var[id]->GlobalStop = GTimeP->times; } if((status = GetAttribute(id, SAMPLNAME)) < 0) DD_Var[id]->MinGap = MINGAP; else { DD_Var[id]->MinGap = *((double *)((DD_Var[id]->AttrData).Variables[0])) * 5.0; if(DD_Var[id]->MinGap < MINGAP) DD_Var[id]->MinGap = MINGAP; } /* ---------------------------------------------------------------- * Read External archiving info * -----------------------------------------------------------------*/ DD_Var[id]->ExtCallAllowed = 0; if((status = GetAttribute(id, REMARCHNAME)) < 0) { if(Verbose) fprintf(stderr,"OpentInstr(%s):RemBase:GetAttribute(%s): %s\n", VInstrName,REMARCHNAME, nc_strerror(status)); DD_Var[id]->ExtCallAllowed = 0; DD_Var[id]->BaseName[0] = '\0'; DD_Var[id]->RemSetID[0] = '\0'; } else { strcpy(DD_Var[id]->BaseName,(DD_Var[id]->AttrData).Variables[0]); if((status = GetAttribute(id, REMINSTNAME)) < 0) { DD_Var[id]->ExtCallAllowed = 0; if(Verbose) fprintf(stderr,"OpentInstr(%s):RemInstr: %s\n",VInstrName,nc_strerror(status)); } else { DD_Var[id]->ExtCallAllowed = 1; strcpy(DD_Var[id]->RemSetID,(DD_Var[id]->AttrData).Variables[0]); } } if(Verbose) fprintf(stderr,"OpentInstr(%s): GStart: %f GStop: %f\n",VInstrName,DD_Var[id]->GlobalStart,DD_Var[id]->GlobalStop); if(Verbose) fprintf(stderr,"OpentInstr(%s): RemBase: %s RemInstr: %s\n",VInstrName,DD_Var[id]->BaseName,DD_Var[id]->RemSetID); if(Verbose) fprintf(stderr,"DD_GetData:OpentInstr: New ID = %d\n",id); return(id); } /*-------------------------------------------------------------------------------*/ /*###########################################################*/ /*------------------- CLOSEID -------------------------------*/ /*###########################################################*/ int CloseID(int ID) /* * Closes this ID and return number of IDs remained in use */ { int status; int i,il, count = 0; /* Is this ID */ if(Verbose) fprintf(stderr,"CloseID(%d)\n",ID); if(ID >= MaxIDNumber) return(1); /* Everythig is OK */ if(DD_Var[ID] != NULL) { /** if(Verbose) fprintf(stderr,"CloseID(%d): ID exists, start termination\n",ID); **/ /*------ Close all netCDF files -----*/ if(DD_Var[ID]->ncID >= 0) { status = nc_close(DD_Var[ID]->ncID); DD_Var[ID]->ncID = -1; Cache_ReleaseDataFileAccess(DD_Var[ID]); /** if(Verbose) fprintf(stderr,"CloseID(%d): Data File is closed\n",ID); **/ } //Close cache file Cache_CloseFile(DD_Var[ID]); if(DD_Var[ID]->attrID >= 0) { status = nc_close(DD_Var[ID]->attrID); DD_Var[ID]->attrID = -1; /** if(Verbose) fprintf(stderr,"CloseID(%d): Info File is closed\n",ID); **/ } if(DD_Var[ID]->tmID >= 0) { status = nc_close(DD_Var[ID]->tmID); DD_Var[ID]->tmID = -1; /** if(Verbose) fprintf(stderr,"CloseID(%d): Times File is closed\n",ID); **/ } /*========================================================== * FREE MEMORY Variable Data *==========================================================*/ for(il = 0; il < DD_Var[ID]->ParamSize; il++) { for(i = 0; i < DD_Var[ID]->VarData[il].VarNumber; i++) { if (Verbose) fprintf(stderr,"CloseID(%d): %d, ptr %p\n",ID,i,DD_Var[ID]->VarData[il].Variables[i]); free(DD_Var[ID]->VarData[il].Variables[i]); // DD_Var[ID]->VarData[il].VarNumber = 0; } //EB - 19/01/16 - OUT of i-loop!!! DD_Var[ID]->VarData[il].VarNumber = 0; free(DD_Var[ID]->VarData[il].Dimensions); } if(DD_Var[ID]->ParamSize > 0) free(DD_Var[ID]->VarData); /** if(Verbose) fprintf(stderr,"CloseID(%d): Free VarData\n",ID); **/ if(DD_Var[ID]->AttrData.Variables != NULL) { /** if (Verbose) fprintf(stderr,"CloseID(%d): Free AttrData.Variables[0] = %p\n",ID,DD_Var[ID]->AttrData.Variables[0]); **/ if (DD_Var[ID]->AttrData.Variables[0] != NULL) { free(DD_Var[ID]->AttrData.Variables[0]); DD_Var[ID]->AttrData.Variables[0] = NULL; } } free(DD_Var[ID]); DD_Var[ID] = NULL; if(Verbose) fprintf(stderr,"CloseID(%d): Free DD_Var\n",ID); } /* Count determination */ for(i = 0; i < MaxIDNumber; i++) if(DD_Var[i] != NULL) count++; return(count); } /*###########################################################*/ /*------------------ GETATTRIBUTE ---------------------------*/ /*###########################################################*/ int GetAttribute(int ID, char *VarName) /* * Get information variable by ID and variable * name. Fill Variable structure */ { int VarID; /* ID of requested Variable */ static size_t DimArray[NC_MAX_DIMS]; static int IntDimArray[NC_MAX_DIMS]; static int DimIDArray[NC_MAX_DIMS]; static size_t start[NC_MAX_DIMS]; static void *CommonAttrPnt = NULL; /* Pointer to the Atributes for ALL ID's */ static nc_type type; size_t count = 1; int i, status; /* Check the ID */ if(DD_Var[ID] == NULL) return(NOID); if(Verbose) fprintf(stderr,"GetAttribute(%d): Name = %s\n",ID,VarName); /* Free memory for data */ if(DD_Var[ID]->AttrData.Dimensions == NULL) DD_Var[ID]->AttrData.Dimensions = (int *)IntDimArray; if(DD_Var[ID]->AttrData.Variables == NULL) DD_Var[ID]->AttrData.Variables = &CommonAttrPnt; /* Static pointer -> Variables[0] */ if(DD_Var[ID]->AttrData.Variables[0] != NULL) /* Only one variable exists (no time) */ { /**/ if (Verbose) fprintf(stderr,"GetAttribute(%d):Free AttrData.Variables[0] = %p\n", ID,DD_Var[ID]->AttrData.Variables[0]); /**/ free(DD_Var[ID]->AttrData.Variables[0]); DD_Var[ID]->AttrData.Variables[0] = NULL; } /* Try to open constant information data */ status = nc_open(DD_Var[ID]->AttrName,NC_NOWRITE,&(DD_Var[ID]->attrID)); /* Constant information */ if(status!= NC_NOERR) { if(Verbose) fprintf(stderr,"GetAttribute(%d): %s\n",ID,nc_strerror(status)); return(NOINFOFILE); } /* Get ID for queired variable. If not return */ status = nc_inq_varid(DD_Var[ID]->attrID,VarName,&VarID); if(status != NC_NOERR) { if(Verbose) fprintf(stderr,"GetAttribute(%d): %s\n",ID,nc_strerror(status)); return(NOVAR); } /* Get invormation about queried variable */ status = nc_inq_vartype(DD_Var[ID]->attrID,VarID,&type); /* Type of variable */ status = nc_inq_varndims(DD_Var[ID]->attrID,VarID,&(DD_Var[ID]->AttrData.DimNumber)); /* Number of dimansions */ status = nc_inq_vardimid(DD_Var[ID]->attrID,VarID,DimIDArray); /* Array of dimensions IDs */ if(status != NC_NOERR) { if(Verbose) fprintf(stderr,"GETATTR: %s\n",nc_strerror(status)); return(NOVAR); } if(DD_Var[ID]->AttrData.DimNumber == 0) { DD_Var[ID]->AttrData.DimNumber = 1; DimArray[0] = 1; IntDimArray[0] = 1; } else for(i = 0; i < DD_Var[ID]->AttrData.DimNumber; i++) { status = nc_inq_dimlen( DD_Var[ID]->attrID,DimIDArray[i],&(DimArray[i])); /* Dimensions values */ if(status != NC_NOERR) { if(Verbose) fprintf(stderr,"GETATTR: %s\n",nc_strerror(status)); return(NOVAR); } IntDimArray[i] = (int)DimArray[i]; } /* Define type of variable */ switch(type) { case NC_DOUBLE: DD_Var[ID]->AttrData.type = DD_DOUBLE; break; case NC_CHAR: DD_Var[ID]->AttrData.type = DD_CHAR; break; case NC_FLOAT: DD_Var[ID]->AttrData.type = DD_FLOAT; break; case NC_SHORT: DD_Var[ID]->AttrData.type = DD_SHORT; break; case NC_INT: DD_Var[ID]->AttrData.type = DD_INT; } /* Setting Dimensions attributes to get data */ for(i = 0; i < DD_Var[ID]->AttrData.DimNumber; i++) count = count * DimArray[i]; /* Alocating memory for data */ DD_Var[ID]->AttrData.Variables[0] = (void *)malloc(unixlen[DD_Var[ID]->AttrData.type]*count); /* if (Verbose) fprintf(stderr,"Malloc DD_Var[%d]->AttrData.Variables[0] = %p\n",ID,DD_Var[ID]->AttrData.Variables[0]); */ switch(type) { case NC_DOUBLE: status = nc_get_vara_double(DD_Var[ID]->attrID,VarID,start,DimArray,(double *)DD_Var[ID]->AttrData.Variables[0]); if (status != NC_NOERR) { if(Verbose) fprintf(stderr,"GETATTR: %s\n",nc_strerror(status)); return(NOVAR); } break; case NC_CHAR: status = nc_get_vara_text(DD_Var[ID]->attrID,VarID,start,DimArray,(char *)DD_Var[ID]->AttrData.Variables[0]); if (status != NC_NOERR) { if(Verbose) fprintf(stderr,"GETATTR: %s\n",nc_strerror(status)); return(NOVAR); } break; case NC_FLOAT: status = nc_get_vara_float(DD_Var[ID]->attrID,VarID,start,DimArray,(float *)DD_Var[ID]->AttrData.Variables[0]); if (status != NC_NOERR) { if(Verbose) fprintf(stderr,"GETATTR: %s\n",nc_strerror(status)); return(NOVAR); } break; case NC_SHORT: status = nc_get_vara_short(DD_Var[ID]->attrID,VarID,start,DimArray,(short *)DD_Var[ID]->AttrData.Variables[0]); if (status != NC_NOERR) { if(Verbose) fprintf(stderr,"GETATTR: %s\n",nc_strerror(status)); return(NOVAR); } break; case NC_INT: status = nc_get_vara_long(DD_Var[ID]->attrID,VarID,start,DimArray,(long *)DD_Var[ID]->AttrData.Variables[0]); if (status != NC_NOERR) { if(Verbose) fprintf(stderr,"GETATTR: %s\n",nc_strerror(status)); return(NOVAR); } } if(DD_Var[ID]->attrID >= 0) nc_close(DD_Var[ID]->attrID); DD_Var[ID]->attrID = -1; return(1); } /*--------------------------------------------------------------*/ /*############################################################## *# GetMultiData() # /*##############################################################*/ int GetMultiData(int ID, int VarSize, char **VarNames, char *TimeInt, int BackFlag) /* * Create static DD_data_t variables array and return its pointer. * After open a new file the function refreshes variable dimensions * Data are returned by portions until end of requested interval. * Return MOREDATA or OK, or error value. * If requsted variable is "Time", then it converts into "double" form. * The rool of this routine: DO NOT CALL SetNewFile if VI is locked, * If VI have been locked and then have been releesed, Times has to be updated and * SetTime has to be redone. */ { static int *VarID = NULL; /* IDs of requested Parameters of this VI */ static char TimeStr[TIMELENGTH]; static char TimeName[] = "Time"; static int TimeID; //static size_t DimArray[NC_MAX_DIMS]; static size_t **DimArrayS = NULL; /* Several Dimensions arrays */ size_t *DimArray; /* Local Dimension Array (for the specific parameter */ static int DimIDArray[NC_MAX_DIMS]; static nc_type type; static size_t start[NC_MAX_DIMS]; static size_t TimeCount[2] = {1,TIMELENGTH}; static size_t TimeStart[2] = {0,0}; static int Scalar = 0; /* indicator of scalar value */ static int String = 0; /* indicator of single (not timed) string March 9 1997 */ static int TimeTypeValue = 0; /* indicator of time type value */ static size_t RecordSize; /* Size of one record in terms of variables of specified type */ static size_t *PacketSize=NULL; /* Packets sizes of one record (of specified variable) */ static size_t RecordNumber; /* Variable maximal number of records in one packet */ int i,il; int DimNumber; int err2,status; int CurrncID; /*------------------------------------------------------------- * Following variables subsitute fields in DD_Var to save a time *------------------------------------------------------------*/ static DD_Var_t Local; /** sleep(60); **/ /** if(Verbose) { for(il = 0; il < VarSize; il++) fprintf(stderr,"GetMultiData(ID=%d), VarName=%s,Timeint=%s)\n",ID,VarNames[il],TimeInt); fprintf(stderr,"GeMultitData(ID=%d) LastPacket: %d FileStatus: %d NewFile: %d NFWasOpen: %d\n",ID, DD_Var[ID]->LastPacketFlag, DD_Var[ID]->LastFileStatus, DD_Var[ID]->NewFile, DD_Var[ID]->NewFileWasOpen); fprintf(stderr,"GetMultiData(ID=%d), DD_Var[ID]->VarData = %p\n",ID,DD_Var[ID]->VarData); } **/ /* Check the ID and reset the variable number*/ if(DD_Var[ID] == NULL) return(NOID); //if(FirstFlag) { DD_Var[ID]->ParamSize = 0; FirstFlag = 0;} /* sleep(30); */ /* To give possibility to start gdb */ /*=================================================== * Free data from the previous requests * BUT the data dimensions are not removed YET * Probably we have just fill new portion of the same data *==================================================*/ for(il = 0; il < DD_Var[ID]->ParamSize; il++) { for(i = 0; i < DD_Var[ID]->VarData[il].VarNumber; i++) { //if (Verbose) fprintf(stderr," FREE ID = %d, il = %d, i = %d ptr %p\n",ID,il,i,DD_Var[ID]->VarData[il].Variables[i]); free(DD_Var[ID]->VarData[il].Variables[i]); // DD_Var[ID]->VarData[il].VarNumber = 0; } //EB - 19/01/16 - OUT of i-loop!!! DD_Var[ID]->VarData[il].VarNumber = 0; //BRE - 17/09/15 - Free variables !! if(((DD_Var[ID]->LastPacketFlag == OK) || DD_Var[ID]->NewFile) && (DD_Var[ID]->VarData[il].Variables != NULL)) // Request been finished or // System was trying to open new file { free(DD_Var[ID]->VarData[il].Variables); DD_Var[ID]->VarData[il].Variables = NULL; } } /*============================================================================ *###### Check if we need to refresh entire information about parameters ##### *###### We have to renovate ALL if previous request been finished or ##### *###### new file was open during previous entry ##### *============================================================================*/ if((DD_Var[ID]->LastPacketFlag == OK) || DD_Var[ID]->NewFile) // Request been finished or // System was trying to open new file { if(DD_Var[ID]->ncID < 0) return NOPOINTER; /* Time has been not set */ if(Verbose) fprintf(stderr,"GetMultiData(%d): Parameters Info should be updated\n", ID); /** sleep(60); **/ /*--------------------------------------------------------------------- * Look if the LastFileStatus has an error *--------------------------------------------------------------------*/ switch(DD_Var[ID]->LastFileStatus) { case OK: break; /* Data file was open succesfully */ case CACHTOOREC: /* There was no free place in the CACH */ case TRYAGAIN: /* VI was blocked */ case WAITEXTCALL: /* New data was requested at external database */ if(Verbose) fprintf(stderr,"GetData(%d): There was WAITEXTCALL, I am trying again\n",ID); /* We have to check if VI is unlocked */ switch(IsTimesLocked(&Local)) { case NOLOCK: break; case LOCKED: if(Verbose) fprintf(stderr,"GetData(%d): Data base is still locked\n",ID); DD_Var[ID]->VILocked = Local.VILocked; return MOREDELAY; break; case LOCKREMOVED: UpdateTimeInfo(&Local); LocalOrigSync(&Local,DD_Var[ID]); SetTime(&Local,Local.CDTime); /* Return to the original status */ if(Verbose) fprintf(stderr,"GetData(%d):Lock Was removed, SetTime again",ID); } switch(DD_Var[ID]->LastFileStatus = SetNewFile(&Local,1)) /* Only LOCAL work in our case !*/ { case OK: break; /* New file is open, go on */ case CACHTOOREC: /* There was no free place in the CACH */ case TRYAGAIN: /* VI was blocked */ case WAITEXTCALL: /* New data was requested */ DD_Var[ID]->VILocked = Local.VILocked; /* Tell Original holder that it is locked */ DD_Var[ID]->NewFile = 1; DD_Var[ID]->NewFileWasOpen = 1; DD_Var[ID]->LastPacketFlag = MOREDELAY; if(Verbose) fprintf(stderr,"GetData(%d): We have to wait again: %d\n",ID,status); return MOREDELAY; break; case OUTOFTIME: if(Verbose) fprintf(stderr,"GetData(%d): OUTOFTIME while requested new file %d\n",ID,status); DD_Var[ID]->LastFileStatus = OUTOFTIME; DD_Var[ID]->LastPacketFlag = OK; /* Just to show that this request is completed */ return DD_Var[ID]->LastFileStatus; break; default: if(Verbose) fprintf(stderr,"GetData(%d): Unrecoverable error: %d\n",ID,status); DD_Var[ID]->LastPacketFlag = OK; /* Just to show that this request is completed */ return DD_Var[ID]->LastFileStatus; } break; case OUTOFTIME: // Nothing to do with this request. New set time is needed if(Verbose) fprintf(stderr,"GetData(%d): Previous call gave OUTOFTIME, return\n",ID); return DD_Var[ID]->LastFileStatus; break; default: /* The error is unrecoverable */ if(Verbose) fprintf(stderr,"GetData(%d): Unrecoverable error: %d\n",ID,status); return DD_Var[ID]->LastFileStatus; } /*----------------------------------------------------------------------------- * Data file is open. It is time to refresh information about parameters *----------------------------------------------------------------------------*/ for(il = 0; il < DD_Var[ID]->ParamSize; il++) // Free existing dimensions { if(DD_Var[ID]->VarData[il].Dimensions != NULL) {free(DD_Var[ID]->VarData[il].Dimensions); DD_Var[ID]->VarData[il].Dimensions = NULL;} if(DimArrayS[il] != NULL) {free(DimArrayS[il]); DimArrayS[il] = NULL;} } if(DD_Var[ID]->ParamSize > 0) { if(DD_Var[ID]->VarData != NULL) { free(DD_Var[ID]->VarData); DD_Var[ID]->VarData = NULL;} free(VarID); free(PacketSize); free(DimArrayS); } DD_Var[ID]->ParamSize = (size_t)VarSize; /*-------------------------------------------- * Create a new holder according to the parameters number *--------------------------------------------*/ DD_Var[ID]->VarData = (DD_data_t *)malloc(sizeof(DD_data_t) * VarSize); VarID = (int *)malloc(sizeof(int) * VarSize); PacketSize = (size_t *)malloc(sizeof(size_t) * VarSize); DimArrayS = (size_t **)malloc(sizeof(size_t *) * VarSize); for(il = 0; il < DD_Var[ID]->ParamSize; il++) DimArrayS[il] = NULL; /*---------------------------------------------------- * Decide which ncID we are using *---------------------------------------------------*/ if(DD_Var[ID]->NewFile == 1) CurrncID = Local.ncID; else CurrncID = DD_Var[ID]->ncID; /*------------------------------------------------ * Calculation what number of records * of the maximaly sized variable we can transmit *-----------------------------------------------*/ RecordNumber = MaxRecord(CurrncID); if(RecordNumber <= 0) { if(Verbose) fprintf(stderr,"GetMultiData(%d): Error in calculation of records number\n",ID); return(INTSERERR); } /*--------------------------------------------- * Define time ID *--------------------------------------------*/ status = nc_inq_varid(CurrncID,TimeName,&TimeID); /*------------------------------------------------------------------------------------------ * Reseting VarNumber and create a new local data structure * Also we need to set Time limit constants *------------------------------------------------------------------------------------------*/ if(DD_Var[ID]->LastPacketFlag == OK) /* Very new request, after SetTime() */ { TimeStart[0] = DD_Var[ID]->nc_rec; status = nc_get_vara_text(DD_Var[ID]->ncID,TimeID,TimeStart,TimeCount,TimeStr); DD_Var[ID]->CDTime = DD_Time2Double(TimeStr); /* Current time of record */ DD_Var[ID]->SDTime = DD_Var[ID]->CDTime; /* Start time of record */ DD_Var[ID]->FDTime = DD_Var[ID]->SDTime + DD_Time2Double(TimeInt); } DD_Var[ID]->NewFile = 0; /* Forget that it was new file */ /*-------------------------------------------------- * Get Dimensions and allocate memory for all * requested parameters *-------------------------------------------------*/ for(il = 0; il < VarSize; il++) { DD_Var[ID]->VarData[il].VarNumber = 0; status = nc_inq_varid(CurrncID,VarNames[il],&(VarID[il])); if (status != NC_NOERR) { if(Verbose) { fprintf(stderr,"MultiData(%d): NCDF message: %s\n",ID,nc_strerror(status)); fprintf(stderr,"MultiData(%d): Parameter %s not found\n",ID,VarNames[il]); } VarID[il] = NOVAR; /* NOVAR */ } /*-------------------------------------------------------- * Get dimensions number and its type *------------------------------------------------------*/ if(VarID[il] != NOVAR) { DimArrayS[il] = (size_t *)malloc(sizeof(size_t) * NC_MAX_DIMS); DimArray = DimArrayS[il]; // Just a local pointer status = nc_inq_vartype(CurrncID,VarID[il],&type); status = nc_inq_varndims(CurrncID,VarID[il],&DimNumber); //if(Verbose) fprintf(stderr,"GetMultiData(%d): Dimensions(%d) number = %d\n",ID,il,DimNumber); status = nc_inq_vardimid(CurrncID,VarID[il],DimIDArray); if(DimNumber == 0) { DD_Var[ID]->VarData[il].DimNumber = 1; DimArray[1] = 1; Scalar = 1; // For one parameter call only } else /* Filling the array of Dimensions */ { for(i = 0; i < DimNumber; i++) status = nc_inq_dimlen(CurrncID,DimIDArray[i],&(DimArray[i])); } /*--------------- Several special trucks for single variables (without time) ---------*/ if((DimArray[0]<2) && (DimIDArray[0] != 0)) Scalar = 1; /* If the first dimension is not TIME and lenrgth is 1 or 0 */ if((type == NC_CHAR) && (DimNumber < 2)) String = 1; if(String == 0) DimArray[0] = 1; else DimArray[1] = DimArray[0]; if((String == 0) && (DimNumber == 1)) { DimArray[1] = 1; DimNumber = 2;} if(DimNumber > 1) DD_Var[ID]->VarData[il].DimNumber = DimNumber -1; else DD_Var[ID]->VarData[il].DimNumber = 1; /*---------------------------------------------------------- * Create dimensions, and fill the dimensions array *--------------------------------------------------------*/ DD_Var[ID]->VarData[il].Dimensions = (int *)malloc(sizeof(int)*DimNumber); for(i = 0; i < DD_Var[ID]->VarData[il].DimNumber; i++) { (DD_Var[ID]->VarData[il].Dimensions)[i] = (int)DimArray[i+1]; //if(Verbose) fprintf(stderr,"GetMultiData(%d): Dimensions(%d): dim[%d] = %d\n",ID,il,i,(int)DimArray[i+1]); } /*--------------------------------------------------------------------- * Set Variable type *-------------------------------------------------------------------*/ switch(type) { case NC_DOUBLE: DD_Var[ID]->VarData[il].type = DD_DOUBLE; break; case NC_CHAR: DD_Var[ID]->VarData[il].type = DD_CHAR; break; case NC_FLOAT: DD_Var[ID]->VarData[il].type = DD_FLOAT; break; case NC_SHORT: DD_Var[ID]->VarData[il].type = DD_SHORT; break; case NC_INT: DD_Var[ID]->VarData[il].type = DD_INT; break; case NC_BYTE: DD_Var[ID]->VarData[il].type = DD_CHAR; break; default: DD_Var[ID]->VarData[il].type = DD_CHAR; } /*------------------------------------------------------------------------- * Calculate the corresponding record size, * an allocate memory to fit the RecordNumber records *------------------------------------------------------------------------*/ RecordSize = 1; for(i = 1; i < DimNumber; i++) { RecordSize = RecordSize * DimArray[i]; start[i] = 0; } if(String == 1) RecordSize = DimArray[0]; /* March 9 1997 */ PacketSize[il] = RecordSize*unixlen[DD_Var[ID]->VarData[il].type]; DD_Var[ID]->VarData[il].Variables = (void **)malloc(sizeof(void *) * RecordNumber); /* if (Verbose) fprintf(stderr," Malloc: DD_Var[%d]->VarData[%d].Variables = %p\n",ID, il, DD_Var[ID]->VarData[il].Variables); */ } else { DD_Var[ID]->VarData[il].type = NOVAR; /* To indicate absence of this variable */ PacketSize[il] = 0; DD_Var[ID]->VarData[il].DimNumber = 0; DD_Var[ID]->VarData[il].VarNumber = 0; PacketSize[il] = 0; } } /* FOR il */ /*------------------------------------------- * Create a Local structure *------------------------------------------- */ if(DD_Var[ID]->LastPacketFlag == OK) /* Very new request, after SetTime() */ { memcpy((void *)&Local, (void *)DD_Var[ID], sizeof(DD_Var_t)); /*--- Local structure if it is new request */ //if(Verbose) fprintf(stderr,"GetData(%d): DD_Var[ID] -> Local\n",ID); } if(Verbose) fprintf(stderr,"GetMultiData(ID=%d), Created Local, DD_Var[ID]->VarData = %p\n",ID,DD_Var[ID]->VarData); } /*#######################################################################*/ /* End of refresh information about variable in case of new file * or new request */ /*#######################################################################*/ /*================================================================= * GET DATA *=================================================================*/ if ((Scalar == 1) || (String == 1)) DD_Var[ID]->LastPacketFlag = OK; else DD_Var[ID]->LastPacketFlag = MOREDATA; /*=========================================================== * The loop to get data until time or file finish *===========================================================*/ do { /*---------------------------------------- * Get memory for each variable *-----------------------------------------*/ for(il = 0; il < VarSize; il++) { if( DD_Var[ID]->VarData[il].type >= 0) { DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber] = (void *)malloc(PacketSize[il]); /* if (Verbose) fprintf(stderr,"Malloc: DD_Var[%d]->VarData[%d].Variables[%d] = %p, Size = %d\n",ID, il, DD_Var[ID]->VarData[il].VarNumber, DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber], PacketSize[il]); */ } } if((Scalar == 1) || (String == 1)) { start[0] = 0; } else /* Setup start and looking for a time limit */ { /*---------- Define START from LOCAL struct and read current Time ----------*/ start[0] = Local.nc_rec; TimeStart[0] = Local.nc_rec; status = nc_get_vara_text(Local.ncID,TimeID,TimeStart,TimeCount,TimeStr); Local.CDTime = DD_Time2Double(TimeStr); /* Current time of record */ //fprintf(stderr,"GetData(%d): Start %f Current %f Stop %f\n",ID,Local.SDTime,Local.CDTime,Local.FDTime); //-------------- Check if we have to return by time -------------- if(Local.CDTime > Local.FDTime) /* Return by time. All problem will path to the next GetData */ { /* If new file was open we have to return to original file */ if(Verbose) fprintf(stderr,"GetData(%d): Stop By Time\n",ID); SetOriginPointer(&Local, ID); /*------- Free reserved for nothing last array -------------*/ for(il = 0; il < VarSize; il++) { if(DD_Var[ID]->VarData[il].type >= 0) { free(DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber]); /* if (Verbose) fprintf(stderr,"Free: DD_Var[%d]->VarData[%d].Variables[%d], Pntr %p\n",ID, il, DD_Var[ID]->VarData[il].VarNumber, DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber]); */ } } return OK; } //--------- End return by time --------------- } /*------------------------------------------------------- * Get Data according to its type *-------------------------------------------------------*/ for(il = 0; il < VarSize; il++) { if( DD_Var[ID]->VarData[il].type >= 0) { DimArray = DimArrayS[il]; /* if(Verbose) { for (i = 0; i < DD_Var[ID]->VarData[il].DimNumber+1; i++) fprintf(stderr,"GetMultiData(%d): Variable[%d], Dimension[%d] DimSize = %d\n", ID, il, i,DimArray[i]); fprintf(stderr,"VarID[%d] = %d, type = %d\n",il, VarID[il],DD_Var[ID]->VarData[il].type); } */ switch(DD_Var[ID]->VarData[il].type) { case DD_DOUBLE: status = nc_get_vara_double(Local.ncID, VarID[il], start, DimArray, (double *)DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber]); break; case DD_INT: status = nc_get_vara_int(Local.ncID, VarID[il], start, DimArray, (int *)DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber]); break; case DD_FLOAT: status = nc_get_vara_float(Local.ncID, VarID[il], start, DimArray, (float *)DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber]); // if(Verbose) fprintf(stderr,"(Variable[%d])[0] = %f\n",il,((float *)DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber])[0]); break; case DD_SHORT: status = nc_get_vara_short(Local.ncID, VarID[il], start, DimArray, (short *)DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber]); break; case DD_CHAR: status = nc_get_vara_text(Local.ncID, VarID[il], start, DimArray, (char *)DD_Var[ID]->VarData[il].Variables[DD_Var[ID]->VarData[il].VarNumber]); } /* End of switch */ DD_Var[ID]->VarData[il].VarNumber++; } /* if not NOVAR */ } /* for il */ /*------ Return immediately if it is just one record ------------*/ if ((Scalar == 1) || (String == 1)) return OK; /*---- Now we have to decide if we opVarNamesen a new file to continue ------------*/ if(DD_Var[ID]->LastPacketFlag == MOREDATA) /* Timed variable (no scalar) */ { Local.nc_rec++; /*====================================================================== * The next procedure runs if the current file is finished and we have * to open a new file (or look for external data source *=====================================================================*/ if(Local.nc_rec > Local.Maxnc_rec - 1) { if(Verbose) fprintf(stderr,"GetData(%d): Stop By EOF\n",ID); /* Before open new file we have to check the LOCK status */ switch(IsTimesLocked(&Local)) { case NOLOCK: break; case LOCKED: DD_Var[ID]->LastFileStatus = TRYAGAIN; DD_Var[ID]->VILocked = Local.VILocked; /* Tell Original holder that it is locked */ DD_Var[ID]->NewFile = 1; DD_Var[ID]->NewFileWasOpen = 1; return MOREDELAY; break; case LOCKREMOVED: UpdateTimeInfo(&Local); LocalOrigSync(&Local,DD_Var[ID]); SetTime(&Local,Local.CDTime); /* Return to the original status */ } switch(DD_Var[ID]->LastFileStatus = SetNewFile(&Local,1)) { case OK: // Everything is OK DD_Var[ID]->LastPacketFlag = MOREDATA; DD_Var[ID]->NewFile = 1; // We have to reset all variables DD_Var[ID]->NewFileWasOpen = 1; //BRE - Update the current opened file DD_Var[ID]->CurrCushN = Local.CurrCushN; DD_Var[ID]->ncID = Local.ncID; if(Verbose) fprintf(stderr,"GetMultiData(ID=%d), Retun by EOF, MOREDATA, DD_Var[ID]->VarData = %p\n",ID,DD_Var[ID]->VarData); return MOREDATA; case TRYAGAIN: // just wait and try again if(Verbose) fprintf(stderr,"GetData(%d): Open New File return TRYAGAIN\n",ID); DD_Var[ID]->NewFile = 1; DD_Var[ID]->NewFileWasOpen = 1; DD_Var[ID]->LastPacketFlag = MOREDELAY; DD_Var[ID]->VILocked = Local.VILocked; /* Tell Original holder that it is locked */ return MOREDELAY; case WAITEXTCALL: // just wait and try again if(Verbose) fprintf(stderr,"GetData(%d): Open New File returned WAITEXTCALL\n",ID); DD_Var[ID]->VILocked = Local.VILocked; /* Tell Original holder that it is locked */ DD_Var[ID]->NewFile = 1; DD_Var[ID]->NewFileWasOpen = 1; DD_Var[ID]->LastPacketFlag = MOREDELAY; return MOREDELAY; case CACHTOOREC: // just wait and try again if(Verbose) fprintf(stderr,"GetData(%d): Open New File returned CACHTOOREC\n",ID); DD_Var[ID]->NewFile = 1; DD_Var[ID]->NewFileWasOpen = 1; DD_Var[ID]->LastPacketFlag = MOREDELAY; return MOREDELAY; case OUTOFTIME: // Return data as the last packet (as well as it was finished by time if(Verbose) fprintf(stderr,"GetData(%d): New file is out of time\n",ID); SetOriginPointer(&Local, ID); DD_Var[ID]->LastPacketFlag = OK; DD_Var[ID]->NewFile = 1; return OK; break; default: // Unrecoverable error in the database or out of time if(Verbose) fprintf(stderr,"GetData(%d): Unrecoverable error in the new file\n",ID); Local.nc_rec--; DD_Var[ID]->LastPacketFlag = OK; DD_Var[ID]->NewFile = 0; return DD_Var[ID]->LastFileStatus; } } /* End of file finish processing */ if(DD_Var[ID]->VarData[0].VarNumber >= RecordNumber) /* Packet size exceeded */ { DD_Var[ID]->LastPacketFlag = MOREDATA; return MOREDATA; } } /* End of check of status */ } while(1); return OK; } /*-----------------------------------------------------------------*/ /*################################################################# * SET TIME * Set time and try to open appropriate data file. If not try to * call external archive * Return: * NOID - call with uncorrect VI holder * OUTOFTIME - Requested time is out of General time limitation * WAITEXTCALL - Server sent request to external archive * TRYAGAIN - VI is blocked by call to external database * NODATAATTIME - request time is inside NODATA time interval * some return of SetNewFile(); see ... *#################################################################*/ int SetTime(DD_Var_t *DD_VarL, double VCTime) { char Name[MAXSETLENGTH]; /* Name of data nc file */ char FullName[PATHLENGTH]; /* Full name of nc file */ char StartTime[TIMELENGTH]; char StopTime[TIMELENGTH]; static char StartName[] = "StartTime"; static char StopName[] = "StopTime"; static char TimeName[] = "Time"; int StartID,StopID,TimeID; size_t Rmin,Rmax,RLeft,RRight; /* Limits of record num */ double dt, TestTime,MinTime,MaxTime; dd_tmstr_t *tt; int More; /* InsideFlag - we are inside good time interval */ /* NoDataFlag - we in the time record marked "NODATA" */ char TimeIntName[MAXSETLENGTH]; /* File name associated with the given time interval */ static size_t start[2] = {0,0}; static size_t TimeCount[2] = {1,TIMELENGTH}; static size_t FileCount[2] = {1,MAXFILENAME}; static void *p; static double CTime = 0.0; /* Real working requested time */ int status; int SearchStatus; /* Status at the end of interval search */ int ExternalReqStatus; /* Status at return of extenal call */ /* Check the ID */ /** sleep(40); **/ if(Verbose) fprintf(stderr,"SetTime(%f): Start\n",VCTime); if(DD_VarL == NULL) return(NOID); /*=========================================================== * Set CTime if need *===========================================================*/ if(VCTime > 0) { CTime = VCTime; if(Verbose) fprintf(stderr,"SetTime(%f): CTime is from argument\n",CTime); } else if(Verbose) fprintf(stderr,"SetTime(%f): CTime is from saved value\n",CTime); /*---------------------------------------------------- * Check if is out of Global Time Limits * If the requested time is out of Global Time Limit, the time is reset to the * correct time interval *----------------------------------------------------*/ if (CTime <= DD_VarL->GlobalStart) CTime = DD_VarL->GlobalStart + QUANTOFFSET; if (CTime > DD_VarL->GlobalStop) return OUTOFTIME; /* * Check if this VI is not blocked by this or another server */ switch(IsTimesLocked(DD_VarL)) { case NOLOCK: break; case LOCKED: return TRYAGAIN; break; case LOCKREMOVED: UpdateTimeInfo(DD_VarL); } /* * If Ctime out of valid interval, we can try to get new data in external archive */ if((DD_VarL->MinValidTime > CTime)||(DD_VarL->MaxValidTime < CTime)) { if(Verbose) fprintf(stderr,"SetTime(): Start Time is out of current data interval\n"); if(DD_VarL->ExtCallAllowed) { switch(ExternalReqStatus = ExtDataRequest(DD_VarL,CTime)) { case OK: return WAITEXTCALL; /* Request is gone */ case NOEXEC: break; /* Call is impossible */ case NODATAATTIME: return NODATAATTIME; /* CTime in side NODATA interval */ case GAPISSMALL: break; /* Out of data, but gap is too small */ case OUTOFTIME: return OUTOFTIME; default: return OUTOFTIME; } } else return OUTOFTIME; } /* * Now we know that CTime SURE in between Tmin and TMax * We start from the middle of the maximal valid interval */ Rmin = (size_t)DD_VarL->RValidMin; Rmax = (size_t)DD_VarL->RValidMax; More = 1; while(More) { DD_VarL->TimeRecNumber = (Rmin + Rmax)/2; SearchRight(DD_VarL,Rmin,Rmax); /*--- Go right up to valid interval */ start[0] = DD_VarL->TimeRecNumber; status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->StartID,start,TimeCount,StartTime); TestTime = DD_Time2Double(StartTime); if(CTime > TestTime) // StartTime(R) < CTime { status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->StopID,start,TimeCount,StopTime); TestTime = DD_Time2Double(StopTime); if(TestTime >= CTime) /* CTime is really inside this interval */ { More = 0; SearchStatus = INSIDE; } else /* CTime is at the right of the R */ { RLeft = DD_VarL->TimeRecNumber; DD_VarL->TimeRecNumber++; SearchRight(DD_VarL,Rmin,Rmax); /*R shift right up to the next valid interval */ start[0] = DD_VarL->TimeRecNumber; status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->StopID,start,TimeCount,StopTime); TestTime = DD_Time2Double(StopTime); if(TestTime >= CTime) /* CTime is between Stop(R)-1 and Stop(R) */ { More = 0; DD_VarL->CurrRmin = (int)RLeft; DD_VarL->CurrRmax = (int)DD_VarL->TimeRecNumber; /*--- Test if it is inside interval ------*/ status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->StartID,start,TimeCount,StartTime); TestTime = DD_Time2Double(StartTime); if(TestTime < CTime) SearchStatus = INSIDE; else SearchStatus = DATAATRIGHT; /* Ctime is inbetween the valid intervals */ } else /* CTime is on the right from the Stop(R) */ { Rmin = DD_VarL->TimeRecNumber; More = 1; } } /* else of CTime is at the right of the R */ } else /* StartTime(R) > CTime */ { RRight = DD_VarL->TimeRecNumber; DD_VarL->TimeRecNumber--; SearchLeft(DD_VarL,Rmin,Rmax); /*R shift left down to the next valid interval */ start[0] = DD_VarL->TimeRecNumber; status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->StartID,start,TimeCount,StartTime); TestTime = DD_Time2Double(StartTime); if(CTime > TestTime) // CTime is inbetween Start(R) and Start(RRight) { More = 0; DD_VarL->CurrRmax = (int)RRight; DD_VarL->CurrRmin = (int)DD_VarL->TimeRecNumber; /*--- Test if it is inside interval ------*/ status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->StopID,start,TimeCount,StopTime); TestTime = DD_Time2Double(StopTime); if(TestTime > CTime) SearchStatus = INSIDE; else /* Ctime is inbetween the valid intervals */ { DD_VarL->TimeRecNumber++; /* Return to the right interval */ SearchStatus = DATAATRIGHT; /* Ctime is inbetween the valid intervals */ } } else /* CTime is to the left from Start(R) */ { Rmax = DD_VarL->TimeRecNumber; More =1; } } // else StartTime(R) > CTime } // while(More); /*------------------------------------------------------------------------------*/ if(Verbose) fprintf(stderr,"SetTime(): Search Status is %d\n",SearchStatus); /*----------------------------------------------------------------------- * Now we check if we can and need to require new data in external archive *-----------------------------------------------------------------------*/ if((SearchStatus != INSIDE)&&(DD_VarL->ExtCallAllowed)) { switch(ExternalReqStatus = ExtDataRequest(DD_VarL,CTime)) { case OK: return WAITEXTCALL; /* Request is gone */ case NOEXEC: return NODATAATTIME; /* Call is impossible */ case NODATAATTIME: start[0] = DD_VarL->TimeRecNumber; status = nc_get_vara_text(DD_VarL->tmID, DD_VarL->StopID,start,TimeCount,StopTime); CTime = DD_Time2Double(StopTime) + 0.001; if(Verbose) fprintf(stderr,"SetTime(): There was NO Data intreval, CTime is scrolled to %f\n",CTime); return CTIMEISSHIFTED; case GAPISSMALL: DD_VarL->TimeRecNumber = DD_VarL->CurrRmax; break; /* Out of data, but gap is too small */ case OUTOFTIME: return OUTOFTIME; break; default: return OUTOFTIME; } } /* Get the file Name and open file */ if(Verbose) fprintf(stderr,"SetTime(): File found: %d\n",DD_VarL->TimeRecNumber); if((status = SetNewFile(DD_VarL,0)) < 0) return status; /*===================================================================== * Fit the CTime inside data file *=====================================================================*/ /* Get MinTime and MaxTime */ status = nc_inq_varid(DD_VarL->ncID,StartName, &StartID); status = nc_inq_varid(DD_VarL->ncID,StopName, &StopID); status = nc_inq_varid(DD_VarL->ncID,TimeName, &TimeID); if (status != NC_NOERR) { if(Verbose) fprintf(stderr,"SetTime(): %s\n",nc_strerror(status)); return(DATAFILEERR); } start[0] = 0; status = nc_get_vara_text(DD_VarL->ncID, StartID, start,&TimeCount[1],StartTime); MinTime = DD_Time2Double(StartTime); status = nc_get_vara_text(DD_VarL->ncID, StopID, start,&TimeCount[1],StopTime); MaxTime = DD_Time2Double(StopTime); /* circle of finding of time */ More = 1; Rmin = 0; Rmax = DD_VarL->Maxnc_rec - 1; do { start[0] = (Rmin + Rmax)/2; if(start[0] < Rmin) { DD_VarL->nc_rec = Rmin; More = 0;} if(start[0] > Rmax) { DD_VarL->nc_rec = Rmax; More = 0;} if(More > 0) { status = nc_get_vara_text(DD_VarL->ncID, TimeID,start,TimeCount,StartTime); TestTime = DD_Time2Double(StartTime); if(CTime >= TestTime) { // if(start[0] +1 >= DD_VarL->Maxnc_rec) return(OUTOFTIME); if(start[0] +1 >= DD_VarL->Maxnc_rec) // We are in the gap between the last record // and the StopTime of this file { if(Verbose) fprintf(stderr,"SetTime(): The gap between the last record and stop time\n"); if((status = SetNewFile(DD_VarL,1)) < 0) return status; DD_VarL->nc_rec = 0; More = 0; if(Verbose) fprintf(stderr,"SetTime(): Pointer is set as %s, TimesRecord %d FileRecord %d\n",StartTime,DD_VarL->TimeRecNumber, DD_VarL->nc_rec); return 1; } start[0]++; status = nc_get_vara_text(DD_VarL->ncID, TimeID,start,TimeCount,StartTime); TestTime = DD_Time2Double(StartTime); if(CTime <= TestTime) { DD_VarL->nc_rec = start[0]; More = 0; } else { MinTime = TestTime; Rmin = start[0]; More = 1; } } else { if(start[0] <= Rmin) /* 25 Feb 1999 */ { DD_VarL->nc_rec = Rmin; More = 0; } else { start[0]--; status = nc_get_vara_text(DD_VarL->ncID, TimeID,start,TimeCount,StartTime); TestTime = DD_Time2Double(StartTime); if(CTime >= TestTime) { DD_VarL->nc_rec = start[0] +1; More = 0; } else { MaxTime = TestTime; Rmax = start[0]; More = 1; } } } } if(MaxTime - MinTime < 0.0001) { DD_VarL->nc_rec = start[0]; More = 0; } } while(More == 1); if(Verbose) fprintf(stderr,"SetTime(): Pointer is set as %s, TimesRecord %d FileRecord %d\n",StartTime,DD_VarL->TimeRecNumber, DD_VarL->nc_rec); return(1); } /*======================================================================================*/ /*--------------------------------------------------------------------------------------*/ /* If There was TimeUpdate in one VI, vi have to update all other values in another VI */ /*--------------------------------------------------------------------------------------*/ int LocalOrigSync(DD_Var_t *Local, DD_Var_t *Orig) { Orig->tmID = Local->tmID; Orig->NameID = Local->NameID; Orig->StartID = Local->StartID; Orig->StopID = Local->StopID; Orig->RValidMin = Local->RValidMin; Orig->RValidMax = Local->RValidMax; Orig->MinValidTime = Local->MinValidTime; Orig->MaxValidTime = Local->MaxValidTime; Orig->CurrRmin = -1; Orig->CurrRmax = -1; Orig->VILocked = Local->VILocked; return 1; } /*--------------------------------------------------------------------------------------*/ /* Recovering of the original pointer */ /*--------------------------------------------------------------------------------------*/ int SetOriginPointer(DD_Var_t *LocalVI, int ID) { if(DD_Var[ID]->NewFileWasOpen) { switch(IsTimesLocked(LocalVI)) { case NOLOCK: break; case LOCKED: DD_Var[ID]->LastFileStatus = TRYAGAIN; DD_Var[ID]->LastPacketFlag = MOREDELAY; DD_Var[ID]->VILocked = LocalVI->VILocked; /* Tell Original holder that it is locked */ DD_Var[ID]->NewFile = 0; DD_Var[ID]->NewFileWasOpen = 1; return MOREDELAY; break; case LOCKREMOVED: UpdateTimeInfo(LocalVI); LocalOrigSync(LocalVI,DD_Var[ID]); SetTime(DD_Var[ID],DD_Var[ID]->SDTime); /* Return to the original status */ DD_Var[ID]->LastPacketFlag = OK; DD_Var[ID]->NewFileWasOpen = 0; DD_Var[ID]->NewFile = 0; DD_Var[ID]->LastFileStatus = OK; /* Total reset */ return OK; } /* If VI is not locked, try to set new file */ switch(DD_Var[ID]->LastFileStatus = SetNewFile(DD_Var[ID],0)) { case OK: // Everything is OK DD_Var[ID]->LastPacketFlag = OK; DD_Var[ID]->NewFile = 0; // We have to reset all variables DD_Var[ID]->NewFileWasOpen = 0; return OK; case TRYAGAIN: // just wait and try again if(Verbose) fprintf(stderr,"GetData(%d): Reset to Origin return TRYAGAIN\n",ID); DD_Var[ID]->NewFile = 0; DD_Var[ID]->NewFileWasOpen = 1; DD_Var[ID]->LastPacketFlag = MOREDELAY; DD_Var[ID]->VILocked = LocalVI->VILocked; /* Tell Original holder that it is locked */ return MOREDELAY; case WAITEXTCALL: // just wait and try again if(Verbose) fprintf(stderr,"GetData(%d): Reset to Origin return WAITEXTCALL\n",ID); DD_Var[ID]->VILocked = LocalVI->VILocked; /* Tell Original holder that it is locked */ DD_Var[ID]->NewFile = 0; DD_Var[ID]->NewFileWasOpen = 1; DD_Var[ID]->LastPacketFlag = MOREDELAY; return MOREDELAY; case CACHTOOREC: // just wait and try again if(Verbose) fprintf(stderr,"GetData(%d): Reset to Origin returnCACHTOOREC\n",ID); DD_Var[ID]->NewFile = 0; DD_Var[ID]->NewFileWasOpen = 1; DD_Var[ID]->LastPacketFlag = MOREDELAY; return MOREDELAY; case OUTOFTIME: // An accident when we were trying to return to original file default: // Unrecoverable error in the database or out of time if(Verbose) fprintf(stderr,"GetData(%d): Reset to origin: Unrecovararable errorn (including OUT OF TIME)\n",ID); DD_Var[ID]->LastPacketFlag = OK; DD_Var[ID]->NewFile = 0; DD_Var[ID]->NewFileWasOpen = 1; return DD_Var[ID]->LastFileStatus; } } /* If we did not transfer to new file, we can just reset all */ DD_Var[ID]->VILocked = LocalVI->VILocked; /* Tell Original the locking state */ DD_Var[ID]->LastPacketFlag = OK; DD_Var[ID]->NewFileWasOpen = 0; DD_Var[ID]->NewFile = 0; DD_Var[ID]->LastFileStatus = OK; } /*######################################################################################*/