/** * @file ExtDataRequest.c * @version $Id: ExtDataRequest.c,v 1.6 2009/07/07 12:24:23 budnik Exp $ *===================================================================== * ExtDataRequest.c * V.2.6 * Functions set to call external script to get more data for * current database. * * Versions: * Aug 3, 2007, V.1.0, Fedorov * Sep 20, 2007, V.2.0, Fedorov, New solution for IsTimesLocked() * Sep 20, 2007, V.2.1, Fedorov, New solution for IsTimesLocked() * Sep 25, 2007, V.2.2, Fedorov, Variable GAP * May 21, 2008, V.2.3, Fedorov, skip no data file * May 22, 2008, V.2.4, Fedorov, Measuring of elapsed time of Lock * Apr 11, 2009, V.2.5, Fedorov, Do not call new file if the data out of general limits * Jul 07, 2009, V.2.6, Budnik, Special external call if there is empty times.nc; * if(DStop <= DD_Var->GlobalStart) * if(DStart >= DD_Var->GlobalStop) *=====================================================================*/ #include #include #include "DD.h" #include "DD_comm.h" extern int Verbose; /*===================================================================== * Double2ISOTime() * Covert double time to ISO time * return pointer to statis string inside function *=====================================================================*/ char *Double2ISOTime(double CTime) { static char ISO[25]; unsigned *UT; UT = Double2UT(CTime); sprintf(ISO,ISOTIMEP,UT[0],UT[1],UT[2],UT[3],UT[4],UT[5],UT[6]); return (char *)ISO; } /*===================================================================== * DoRequest * Read request. * return OK, or NOEXEC *=====================================================================*/ int DoRequest(DD_Var_t *DD_Var, double Start, double Stop) { static char Command[MAXCOMMANDL]; /*Memory for command in system() */ static char StartISO[25],StopISO[25]; int err; struct timeval tv; struct timezone tz; /*====================================================== * Lock the VI * Set 1 means that VI is locked by THIS DD_Var and external program did not set LockFile yet *=====================================================*/ DD_Var->VILocked = 1; gettimeofday(&tv,&tz); memcpy(&(DD_Var->LockStartTime),&(tv.tv_sec),sizeof(time_t)); strcpy(StartISO,Double2ISOTime(Start)); strcpy(StopISO,Double2ISOTime(Stop)); sprintf(Command,GETNEWDATACALL,getenv("DDBASEBIN"),DD_Var->BaseName,DD_Var->RemSetID,DD_Var->path,StartISO,StopISO); if(Verbose) fprintf(stderr, "DoRequest(): Command = %s\n", Command); err = system(Command); switch(err) { case 0: return OK; case NOPHP: return NOEXEC; case NOSCRIPT: return NOEXEC; default: return NOEXEC; } return NOEXEC; } /*====================================================================== * ExtDataRequest * Return folowing values: * OK - request is accepted SERVER has to wait when LOCK file is gone * NOEXEC - error in external executable * NODATAATTIME - time corresponds to the NODATA interval * GAPISSMALL - Time is inside too small gap *======================================================================*/ int ExtDataRequest(DD_Var_t *DD_Var, double CTime) { size_t Rmin,Rmax; static size_t start[2] = {0,0}; static size_t TimeCount[2] = {1,TIMELENGTH}; char StartTime[TIMELENGTH]; char StopTime[TIMELENGTH]; double DStart, DStop; int SearchResult, More, status; if(Verbose) fprintf(stderr,"ExtDataRequest: Rmin,Rmax = %d %d, CTime = %f\n",DD_Var->CurrRmin,DD_Var->CurrRmax, CTime); /* * Search if there is an emtpy space ... */ if(DD_Var->CurrRmin >= 0) Rmin = (size_t)DD_Var->CurrRmin; else Rmin = 0; if(DD_Var->CurrRmax >= 0) Rmax = (size_t)DD_Var->CurrRmax; else Rmax = DD_Var->MaxTimeRecNum - 1; if(Verbose) fprintf(stderr,"ExtDataRequest: CTime = %s\n",Double2DD_Time(CTime)); /* * No yet Records in times.nc */ if (Rmax == -1) { DStart = CTime - REQTIMEINT; DStop = CTime + REQTIMEINT; if(DStart > DD_Var->GlobalStop) { if(Verbose) fprintf(stderr, "ExtDataRequest: Request exceeds the global stop\n"); return OUTOFTIME; } if(DStop < DD_Var->GlobalStart) { if(Verbose) fprintf(stderr, "ExtDataRequest: Request is less than global start\n"); return OUTOFTIME; } return DoRequest(DD_Var, DStart, DStop); } More = 1; while(More) { start[0] = (Rmin + Rmax)/2; status = nc_get_vara_text(DD_Var->tmID, DD_Var->StartID,start,TimeCount,StartTime); DStart = DD_Time2Double(StartTime); if(CTime > DStart) { status = nc_get_vara_text(DD_Var->tmID, DD_Var->StopID,start,TimeCount,StopTime); DStop = DD_Time2Double(StopTime); if(DStop >= CTime) /* This is really INSIDE NODATA */ { DD_Var->TimeRecNumber = start[0]; More = 0; return NODATAATTIME; } else /* Try interval at the right */ { if(start[0] >= DD_Var->MaxTimeRecNum - 1) /* It was the last record */ { More = 0; DD_Var->TimeRecNumber = DD_Var->MaxTimeRecNum - 1; SearchResult = DATAATLEFT; /* We are on the right of all records */ } else { if(Verbose) fprintf(stderr,"ExtDataRequest: We have to move to %d record, CTime = %s\n", start[0]+1,Double2DD_Time(CTime)); start[0]++; status = nc_get_vara_text(DD_Var->tmID, DD_Var->StartID,start,TimeCount,StartTime); DStart = DD_Time2Double(StartTime); if(DStart >= CTime) /* No data interval is at the RIGHT */ { DD_Var->TimeRecNumber = start[0]; More = 0; SearchResult = DATAATRIGHT; } else { Rmin = start[0]; if(Rmax <= Rmin) Rmax = Rmin; More = 1; } } /* else start[0] >= maximal */ } /* else of TestTime >= CTime */ } /*(CTime > DStart) */ else /* StartTime(R) > CTime */ { if(start[0] <= 0) /* CTime is on the left from the first interval */ { More = 0; DD_Var->TimeRecNumber = 0; SearchResult = DATAATRIGHT; } else { start[0]--; /* Try interval at the left */ status = nc_get_vara_text(DD_Var->tmID, DD_Var->StopID,start,TimeCount,StopTime); DStop = DD_Time2Double(StopTime); if(CTime > DStop) /* Correct interval is on the right */ { DD_Var->TimeRecNumber = start[0] + 1; More = 0; SearchResult = DATAATRIGHT; } else { Rmax = start[0]; More =1; } } } } /* while(More) */ /* * Probably we at the left or at the right of interval */ if(SearchResult == DATAATLEFT) // Data are on the left of requested data { start[0] = DD_Var->TimeRecNumber; status = nc_get_vara_text(DD_Var->tmID, DD_Var->StopID,start,TimeCount,StopTime); DStart = DD_Time2Double(StopTime); // Left boundary if((CTime - DStart) > REQTIMEINT) DStart = CTime - REQTIMEINT; DStop = CTime + REQTIMEINT; if(DStart >= DD_Var->GlobalStop) { if(Verbose) fprintf(stderr, "ExtDataRequest: Request exceeds the global stop\n"); return OUTOFTIME; } return DoRequest(DD_Var, DStart, DStop); } if(DD_Var->TimeRecNumber == 0) // All data is on the right { start[0] = DD_Var->TimeRecNumber; status = nc_get_vara_text(DD_Var->tmID, DD_Var->StartID,start,TimeCount,StartTime); DStop = DD_Time2Double(StartTime); /* Right boundary */ if((DStop - CTime) > REQTIMEINT) DStop = CTime + REQTIMEINT; DStart = CTime - REQTIMEINT; if(DStop <= DD_Var->GlobalStart) { if(Verbose) fprintf(stderr, "ExtDataRequest: Request is less than global start\n"); return OUTOFTIME; } return DoRequest(DD_Var, DStart, DStop); } /* * Now we are between two records * We have to check if the gap is big enough */ start[0] = DD_Var->TimeRecNumber; status = nc_get_vara_text(DD_Var->tmID, DD_Var->StartID,start,TimeCount,StartTime); DStop = DD_Time2Double(StartTime); /* GAP! */ start[0]--; status = nc_get_vara_text(DD_Var->tmID, DD_Var->StopID,start,TimeCount,StopTime); DStart = DD_Time2Double(StopTime); /* GAP! */ if((DStop - DStart) < DD_Var->MinGap) return GAPISSMALL; if((CTime - DStart) > REQTIMEINT) DStart = CTime - REQTIMEINT; if((DStop - CTime) > REQTIMEINT) DStop = CTime + REQTIMEINT; /* if(Verbose) { fprintf(stderr,"DStart-GlobalStart = %f\n",DStart - DD_Var->GlobalStart); fprintf(stderr,"DStop-GlobalStop = %f\n",DStop - DD_Var->GlobalStop); } if((DStop > DD_Var->GlobalStop) || (DStart < DD_Var->GlobalStart)) return OUTOFTIME; */ return DoRequest(DD_Var, DStart, DStop); } /*====================================================================== * IsTimesLocked * Return 1 if there is LOCK in the VI directory or if the corresponding flag in DD_Var is UP *======================================================================*/ int IsTimesLocked(DD_Var_t *DD_VarL) { int status; char FullPath[PATHLENGTH]; struct timeval tv; struct timezone tz; strcpy(FullPath,DD_VarL->path); strcat(FullPath,DIRLOCK); status = access(FullPath, F_OK); /* negative if there is no file */ switch(DD_VarL->VILocked) { case 0: if(status < 0) return NOLOCK; /* NO LOCK */ else {DD_VarL->VILocked = 2; return LOCKED;} /* LOCK was made by another server */ break; case 1: if(status < 0) /* LOCK was made by THIS server, PHP is not ready yet OR already removed(!)*/ { gettimeofday(&tv,&tz); if(difftime(tv.tv_sec,DD_VarL->LockStartTime) > 1.5) {DD_VarL->VILocked = 0; return LOCKREMOVED;} /* PHP alreadyremoved LOCK */ else return LOCKED; } else {DD_VarL->VILocked = 2; return LOCKED;} /* Now even PHP setup LOCK */ break; case 2: if(status < 0) {DD_VarL->VILocked = 0; return LOCKREMOVED;} /* PHP removed LOCK */ else return LOCKED; /*Keep LOCK condition */ } } /*=============================================================================================*/