/////////////////////////////////////////////////////////////////////////// // This function finds the day containing the last record in database // for the specified interval. // All times are assumed to be unadjusted times. // // static int FindDayContainingClosestEndTime(short sSta, unsigned long ulStartTime, unsigned long ulRequestedEndTime, unsigned long *pulActualEndTime) // // Input: // sSta database number for station // ulStartTime julian seconds of search interval start time // ulRequestedEndTime julian seconds of search interval end time // // Output: // pulActualEndTime julian seconds of the last record in the database in the search interval // // External Dependencies: // Multiple functions to read information from database /////////////////////////////////////////////////////////////////////////// static int FindDayContainingClosestEndTime(short sSta, DATE dStartTime, DATE dRequestedEndTime, DATE *pdActualEndTime) { db_day_rec dbEndDay; int status; DATE dDayStartTime; // verify that the requested interval is a valid one if (dRequestedEndTime < dStartTime) return(uiINVALID_TIME_INTERVAL_ERR); *pdActualEndTime = dRequestedEndTime; // find day containing the requested end time BOOL bSameDayAsStart = FALSE; status = glDbDay.FindDayRecInMainDb(sSta, dRequestedEndTime); if (status != 1) { // day containing ulRequested End not in database *pdActualEndTime = floor(dRequestedEndTime); do { // so back up until you find a day in the database *pdActualEndTime -= 1.0; status = glDbDay.FindDayRecInMainDb(sSta, *pdActualEndTime); if (status == TRUE) { if (d_recread((char*)&dbEndDay, CURR_DB) != S_OKAY) return(uiDB_BAD_ERR); *pdActualEndTime = dbEndDay.d_day_end_time; } //if ((int)dStartTime == (int)*pdActualEndTime) bSameDayAsStart = TRUE; bSameDayAsStart = SameDay(dStartTime, *pdActualEndTime); // 24-May-2005 use function for SameDay } while ((status != TRUE) && (!bSameDayAsStart) && (*pdActualEndTime > dStartTime)); if (status != TRUE) return (uiDAY_NOT_IN_DB_STATUS); // didn't find a day if (*pdActualEndTime < dStartTime) return (uiDAY_NOT_IN_DB_STATUS); } // read the record of the day found if (d_recread((char*)&dbEndDay, CURR_DB) != S_OKAY) return(uiDB_BAD_ERR); if ((*pdActualEndTime != dRequestedEndTime) || (*pdActualEndTime > dbEndDay.d_day_end_time)){ // get new end time if needed *pdActualEndTime = dbEndDay.d_day_end_time; } // if requested end time is before the start of this day, then you must back up further bSameDayAsStart = FALSE; if ((*pdActualEndTime < dbEndDay.d_day_beg_time)){ // check if end time before the start dDayStartTime = *pdActualEndTime; *pdActualEndTime = floor(dDayStartTime); do { *pdActualEndTime -= 1.0; status = glDbDay.FindDayRecInMainDb(sSta, *pdActualEndTime); if (status == TRUE) { if (d_recread((char*)&dbEndDay, CURR_DB) != S_OKAY) return(uiDB_BAD_ERR); *pdActualEndTime = dbEndDay.d_day_end_time; } //if ((int)dStartTime == (int)*pdActualEndTime) bSameDayAsStart = TRUE; bSameDayAsStart = SameDay(dStartTime, *pdActualEndTime); // 24-May-2005 use function for SameDay } while ((status != TRUE) && (!bSameDayAsStart) && (*pdActualEndTime > dStartTime)); if (status != TRUE) return (uiDAY_NOT_IN_DB_STATUS); if (*pdActualEndTime < dStartTime) return (uiDAY_NOT_IN_DB_STATUS); } return(TRUE); }
/////////////////////////////////////////////////////////////////////////// // This function finds the day containing the first record in database // for the specified interval. // // static int FindDayContainingClosestEndTime(short sSta, unsigned long ulStartTime, unsigned long ulRequestedEndTime, unsigned long *pulActualEndTime) // // Input: // sSta database number for station // ulStartTime julian seconds of search interval start time // ulRequestedEndTime julian seconds of search interval end time // // Output: // pulActualEndTime julian seconds of the last record in the database in the search interval // // External Dependencies: // Multiple functions to read information from database /////////////////////////////////////////////////////////////////////////// static int FindDayContainingClosestStartTime(short sSta, DATE dRequestedStartTime, DATE dEndTime, DATE *pdActualStartTime) { struct db_day_rec dbStartDay; int status; DATE dDayStartTime; // verify that the requested interval is a valid one if (dEndTime < dRequestedStartTime) return(uiINVALID_TIME_INTERVAL_ERR); *pdActualStartTime = dRequestedStartTime; BOOL bSameDayAsEnd = FALSE; // find day containing the requested start time status = glDbDay.FindDayRecInMainDb(sSta, dRequestedStartTime); if (status != TRUE) { // day containing ulRequestedStartTime not in database *pdActualStartTime = floor(dRequestedStartTime); do { // move forward until you find a data in the database *pdActualStartTime += 1.0; status = glDbDay.FindDayRecInMainDb(sSta, *pdActualStartTime); if (status == TRUE) { if (d_recread((char*)&dbStartDay, CURR_DB) != S_OKAY) return(uiDB_BAD_ERR); *pdActualStartTime = dbStartDay.d_day_beg_time; } //if ((int)*pdActualStartTime == (int)dEndTime) bSameDayAsEnd = TRUE; bSameDayAsEnd = SameDay(*pdActualStartTime, dEndTime); // 24-May-2005 use function for SameDay } while ((status != TRUE) && (!bSameDayAsEnd) && (*pdActualStartTime < dEndTime)); if (status != TRUE) return (uiDAY_NOT_IN_DB_STATUS); } // read the record of the day found if (d_recread((char*)&dbStartDay, CURR_DB) != S_OKAY) return(uiDB_BAD_ERR); if ((*pdActualStartTime != dRequestedStartTime) || (*pdActualStartTime < dbStartDay.d_day_beg_time)){ /* get new end time if needed */ *pdActualStartTime = dbStartDay.d_day_beg_time; } // if the start time is beyond the last time in this day then must move forward in db to next day if ((*pdActualStartTime > dbStartDay.d_day_end_time)){ dDayStartTime = *pdActualStartTime; *pdActualStartTime = floor(dDayStartTime); bSameDayAsEnd = FALSE; do { *pdActualStartTime += 1.0; status = glDbDay.FindDayRecInMainDb(sSta, *pdActualStartTime); if (status == TRUE) { if (d_recread((char*)&dbStartDay, CURR_DB) != S_OKAY) return(uiDB_BAD_ERR); *pdActualStartTime = dbStartDay.d_day_beg_time; } //if ((int)*pdActualStartTime == (int)dEndTime) bSameDayAsEnd = TRUE; bSameDayAsEnd = SameDay(*pdActualStartTime, dEndTime); // 24-May-2005 use function for SameDay } while ((status != TRUE) && (!bSameDayAsEnd) && (*pdActualStartTime < dEndTime)); if (status != TRUE) return (uiDAY_NOT_IN_DB_STATUS); } return(TRUE); }
int main (int argc, char *argv[]) { struct or_dbrec dbrec; char renamebuf[256]; time_t now; struct tm *time_ptr; _Xltimeparams localtime_buf; aa_argv0 = argv[0]; setlocale (LC_ALL, ""); dtsearch_catd = catopen (FNAME_DTSRCAT, 0); austools_catd = catopen (FNAME_AUSCAT, 0); time (&now); time_ptr = _XLocaltime(&now, localtime_buf); strftime (renamebuf, sizeof (renamebuf), catgets (dtsearch_catd, MS_misc, 22, "%A, %b %d %Y, %I:%M %p"), time_ptr); printf (catgets (dtsearch_catd, MS_misc, 23, "%s: Version %s. Run %s.\n"), aa_argv0, DtSrVERSION, renamebuf); if (argc < 2) { printf (catgets (dtsearch_catd, MS_dbrec, 310, "USAGE: %s <dbname>\n"), aa_argv0); return 2; } sprintf (renamebuf, "%s.d00", argv[1]); db_oflag = O_RDONLY; /* db files may be read-only */ d_open (argv[1], "o"); if (db_status != S_OKAY) { printf (catgets (dtsearch_catd, MS_dbrec, 330, "Could not open '%s' database.\n%s\n"), argv[1], vista_msg(PROGNAME"293")); return 3; } d_recfrst (OR_DBREC, 0); if (db_status != S_OKAY) { printf (catgets (dtsearch_catd, MS_dbrec, 340, "No dbrec record in database '%s'.\n"), argv[1]); return 4; } d_recread (&dbrec, 0); if (db_status != S_OKAY) { printf (catgets (dtsearch_catd, MS_dbrec, 350, "Can't read dbrec record in database '%s'.\n%s\n"), argv[1], vista_msg(PROGNAME"306")); return 5; } swab_dbrec (&dbrec, NTOH); print_dbrec (argv[1], &dbrec); return 0; } /* main() */
/////////////////////////////////////////////////////////////////////////// // Name: ReadDayRecInMainDb // // Description: // For a given station and day, read the associated database record from the // Rad dbVista main db. // Uses unadjusted times. // // Declaration: // int ReadDayRecInMainDb(short sSta, DATE dDay, struct db_day_rec *dbDay) // // Input: sSta number of station want to find day for // dDay day (DATE format) searching for // // Output: dbDay record read from database // // Return: TRUE - day exists // uiDAY_NOT_IN_DB - day does not exist // DB_BAD - unexpected db error // // date / author revision // ----------------- -------- // 26-Jul-1995 SFK Created // 02-Aug-2002 SFK Changed to use DATE timebase (doubles in event rec) ////////////////////////////////////////////////////////////////// int CDbDay::ReadDayRecInMainDb(short sSta, DATE dDay, struct db_day_rec *dbDay) { int db_stat; /* ------------------------------------------------------------------ * Find the day record associated with the number. If the day * does not exist, cannot do anything. * ----------------------------------------------------------------*/ db_stat = FindDayRecInMainDb(sSta, dDay); if (!db_stat) return(db_stat); /* ------------------------------------------------------------------ * Read the record. * ----------------------------------------------------------------*/ db_stat = d_recread(dbDay, CURR_DB); if (db_stat == S_OKAY) return(TRUE); RadReviewMsg(uiDB_BAD_ERR, "ReadDayRecInMainDb", db_stat); // had unexpected db error if get here return(uiDB_BAD_ERR); }
/////////////////////////////////////////////////////////////////////////// // Name: FindDayRecInMainDb // // Description: // Determine if a dbday_rec containing the given time exists in the Rad dbVista // main database for the given station. // Uses unadjusted times. // // Declaration: // int FindDayRec(short sSta, DATE dTime) // // Input: sSta number of station want to find day for // dTime day (DATE format) searching for // // Output: none // // Return: TRUE - day exists // uiDAY_NOT_IN_DB_STATUS - day does not exist // STA_NOT_IN_DB - sSta does not exist // DB_BAD - unexpected db error // // date / author revision // ----------------- -------- // 23-May-1995 SFK Created // 21-Jul-1995 SFK When find day looking for make sure the day is owned by the // expected sSta. // 02-Aug-2002 SFK Changed to use DATE timebase (doubles in event rec) // 23-Sep-2003 SFK Changed name from FindDayRec to FindDayRecInMainDb ////////////////////////////////////////////////////////////////// int CDbDay::FindDayRecInMainDb(short sSta, DATE dTime) { struct db_day_rec dbDay; DATE ddbDay; int db_stat, status; short db_sSta; /* ------------------------------------------------------------------ * If the sSta is not in the database, can't do anything * ----------------------------------------------------------------*/ status = StationExistsInMainDb(sSta); if (status != 1) return(status); /* ------------------------------------------------------------------ * Found the sSta, make it the owner of the set to search * ----------------------------------------------------------------*/ if (d_setor(STATION_TO_DAY_SET, CURR_DB) != S_OKAY) goto db_exit; /* ------------------------------------------------------------------ * Search through the day records attached to this sSta. Read * out the time associated with the day and convert it to the * jul secs corresponding to day start. If this matches the * day looking for then have found it. * ----------------------------------------------------------------*/ db_stat = d_findfm(STATION_TO_DAY_SET, CURR_DB); if (db_stat == S_EOS) return(uiDAY_NOT_IN_DB_STATUS); if (db_stat != S_OKAY) goto db_exit; if (d_crread(D_DAY_BEG_TIME_KEY, &ddbDay, CURR_DB) != S_OKAY) goto db_exit; //db_stat = d_recread(&dbDay, CURR_DB); // debug if ((int)ddbDay == (int)dTime) return 1; do { db_stat = d_findnm(STATION_TO_DAY_SET, CURR_DB); if (db_stat == S_EOS) return(uiDAY_NOT_IN_DB_STATUS); if (db_stat != S_OKAY) goto db_exit; if (d_crread(D_DAY_BEG_TIME_KEY, &ddbDay, CURR_DB) != S_OKAY) goto db_exit; //db_stat = d_recread(&dbDay, CURR_DB); // debug if ((int)ddbDay == (int)dTime) { if (d_csoread(STATION_TO_DAY_SET, S_STA_NUM_KEY, &db_sSta, CURR_DB) != S_OKAY) goto db_exit; db_stat = d_recread(&dbDay, CURR_DB); // debug if (db_sSta == sSta ) return 1; } } while (db_stat == S_OKAY); db_exit: RadReviewMsg(uiDB_BAD_ERR, "FindDayRecInMainDb", db_stat); // had unexpected db error if get here return(uiDB_BAD_ERR); }
/////////////////////////////////////////////////////////////////////////// // Name: GetDataStatistics // Replaces FindIntervalInDb // // Description: // Calculate the number of data points in the database for the specified // station during the requested interval. Determine the first and last // actual times in the db in the interval for the station. // All requests are assumed to be in adjusted times. Data are stored in // the database in unadjusted times. So data values must be properly // adjusted before calls to the respective database holding the data. // // Declaration: // int GetDataStatistics(short sSta, DATE dStartTime, DATE dEndTime, DATE *pdActualStartTime, DATE *pdActualAdjEndTime, unsigned long *pulNumPts) // // Input: sSta number of station want to find statistics for // dStartTime start of search interval // dEndTime end of search interval // // Output: pdActualStartTime timestamp of first data point within interval // pdActualAdjEndTime timestamp of last data point within interval // pulNumPts number of data points within interval // // Return: TRUE - day and associated records deleted // FAIL - day not found in db // DB_BAD - unexpected db error // // date / author revision // ----------------- -------- // 31-MAY-1995 SFK Created from old GRAND Review getpts.c // 09-Feb-1996 SFK Fixed problem exceeding RAW_DATA_RECS_PER_DB_RECORD in index // 22-Oct-1996 SFK Changed to also return actual end time. // 21-Mar-2001 SFK Version 2.07 Added hooks into data residing in Access database // 01-Feb-2002 SFK Integrated with GRAND Com Version 2.10 // 20-May-2002 SFK Integrated with VIFM COM // 07-Aug-2002 SFK Replaced all calls to FindIntervalInDb to this function. ////////////////////////////////////////////////////////////////// // this returns time-aligned data // supports new FacMgr 9-18-2003 int GetDataStatistics( IDStruct StaID, BOOL bStation, DATE dAdjStartTime, DATE dAdjEndTime, DATE *pdActualAdjStartTime, DATE *pdActualAdjEndTime, unsigned long *pulNumPts) { struct db_day_rec dbCurrentDay; // day presently reading struct db_float_data_rec dbfData; // record containing raw float data struct db_double_data_rec dbdData; // record containing raw double data int i, status = 0; DATE dCurrentDay; // day you want to find in database in jul secs unsigned long ulPtsInDayBeforeStart; DATE dStart, dEnd; DATE dActualEndTime, dActualStartTime; unsigned long ulPtsSoFar; BOOL bOnlyOneDay; CGFmtStr msg; short sChan; *pulNumPts = 0; *pdActualAdjStartTime = 0.0; *pdActualAdjEndTime = 0.0; // GRAND or BOT/VIFM or EOSS data in separate COM component that handles time adjustments if (pglTimeAlign->COMDataType(StaID.sStaType)) { if (bStation) { sChan = -1; } else { sChan = StaID.sChanID; } if (StaID.sStaType == EOSS_TYPE) { //Don't use TimeAlign for EOSS. //Use the CEOSSImport class directly. status = pglEOSSImport->GetDataStatistics( glsFacNum, StaID.sStaID, sChan, dAdjStartTime, dAdjEndTime, pdActualAdjStartTime, pdActualAdjEndTime, pulNumPts); } else if (StaID.sStaType == BINARY_TYPE) { status = pglBinaryImport->GetDataStatistics( glsFacNum, StaID.sStaID, sChan, dAdjStartTime, dAdjEndTime, pdActualAdjStartTime, pdActualAdjEndTime, pulNumPts); } else { status = pglTimeAlign->GetDataStatistics( glsFacNum, StaID.sStaID, sChan, dAdjStartTime, dAdjEndTime, pdActualAdjStartTime, pdActualAdjEndTime, pulNumPts, StaID.sStaType); } if (StaID.sStaType != -1) return(status); } // now handle the data in the old dbVista Database which is always on a channel basis // since data are stored in non-adjusted format in database, unadjust the calling times now dStart = UnadjustTimestamp(StaID, dAdjStartTime); dEnd = UnadjustTimestamp(StaID, dAdjEndTime); // all other data types are still in the main dbVista database // find the beginning and end times in the requested interval status = FindDayContainingClosestEndTime(StaID.sStaID, dStart, dEnd, &dActualEndTime); if (status != TRUE) return(status); status = FindDayContainingClosestStartTime(StaID.sStaID, dStart, dActualEndTime, &dActualStartTime); if (status != TRUE) return(status); // handle case of one point if (dActualStartTime == dActualEndTime) { *pdActualAdjStartTime = AdjustTimestamp(StaID, dActualStartTime); *pdActualAdjEndTime = *pdActualAdjStartTime; *pulNumPts = 1; return(TRUE); } // these cases should never happen; if they do return 0 points. if ((dEnd < dActualStartTime) || (dStart > dActualEndTime)) { *pdActualAdjStartTime = dAdjStartTime; *pdActualAdjEndTime = *pdActualAdjStartTime; return 1; } dCurrentDay = dActualStartTime; // find the start time within its multiple record if (StaID.sDataType == FLOAT_TYPE) { status = FindDbDataRecContainingTime(StaID, dActualStartTime, SEARCH_START, &dbfData); // read record containing start time if (status != TRUE) return(status); i = 0; while ((dbfData.d_fdata_time[i] < dActualStartTime) && (i < (RAW_DATA_RECS_PER_DB_RECORD-1)) && (dbfData.d_fdata_time[i] != 0.0)) { // look for the actual start in the multiple record. i++; } if (d_setmr(DAY_TO_FLOAT_DATA_SET, CURR_DB) != S_OKAY) goto db_exit; if (d_csoread(DAY_TO_FLOAT_DATA_SET, UL_DAY_TOTAL_PTS, (char *)pulNumPts, CURR_DB) != S_OKAY) goto db_exit; if ((dbfData.d_fdata_time[i] == 0.0) && (i != 0)) i--; // back up if hit the 0s at end of day as they signal no data //{ // if (i != 0) i--; // back up if hit the 0s at end of day as they signal no data //} ulPtsInDayBeforeStart = dbfData.ul_fdata_pts_so_far + (long)i; *pulNumPts = *pulNumPts - ulPtsInDayBeforeStart; dActualStartTime = dbfData.d_fdata_time[i]; } // find the start time within its multiple record if (StaID.sDataType == DOUBLE_TYPE) { status = FindDbDataRecContainingTime(StaID, dActualStartTime, SEARCH_START, &dbdData); // read record containing start timre if (status != TRUE) return(status); i = 0; while ((dbdData.d_ddata_time[i] < dActualStartTime) && (i < (RAW_DATA_RECS_PER_DB_RECORD-1)) && (dbdData.d_ddata_time[i] != 0.0)) { // look for the actual start in the multiple record. i++; } if (d_setmr(DAY_TO_DOUBLE_DATA_SET, CURR_DB) != S_OKAY) goto db_exit; if (d_csoread(DAY_TO_DOUBLE_DATA_SET, UL_DAY_TOTAL_PTS, (char *)pulNumPts, CURR_DB) != S_OKAY) goto db_exit; if (dbdData.d_ddata_time[i] == 0) if (i != 0.0) i--; // back up if hit the 0s at end of day as they signal no data ulPtsInDayBeforeStart = dbdData.ul_ddata_pts_so_far + (long)i; *pulNumPts = *pulNumPts - ulPtsInDayBeforeStart; dActualStartTime = dbdData.d_ddata_time[i]; } if (dEnd < dActualStartTime) { // requested interval before any real data in day *pdActualAdjStartTime = AdjustTimestamp(StaID, dActualStartTime); *pdActualAdjEndTime = AdjustTimestamp(StaID, dActualEndTime); *pulNumPts = 0; return(TRUE); } // finished with start day, now see if more than one day in the interval bOnlyOneDay = FALSE; if ((int)dActualStartTime == (int)dActualEndTime) bOnlyOneDay = TRUE; // there is more than one day so add the points in each dat to the total if (!bOnlyOneDay) { bool bDone = false; do { // 09-24-98 rewrite handle case of a missing day dCurrentDay = dCurrentDay + 1.0; // go on to the next day in the db if ((int)dCurrentDay == (int)dActualEndTime) { bDone = true; } else { // not on the last day status = glDbDay.FindDayRecInMainDb(StaID.sStaID, dCurrentDay); if (status == TRUE) { if (d_recread((char*)&dbCurrentDay, CURR_DB) != S_OKAY) goto db_exit; *pulNumPts = *pulNumPts + dbCurrentDay.ul_day_total_pts; // add the number of pts in this day to the total } } } while (!bDone); } // on the end day, find the end time within its multiple record if (StaID.sDataType == FLOAT_TYPE) { status = FindDbDataRecContainingTime(StaID, dActualEndTime, SEARCH_END, &dbfData); if (status != TRUE) return(status); i = 0; while ((dbfData.d_fdata_time[i] <= dActualEndTime) && (i < (RAW_DATA_RECS_PER_DB_RECORD-1)) && (dbfData.d_fdata_time[i] != 0.0)) { i++; } // find the actual end time. If at the end of the day record (==0) or // have an exact match, then the end time is that of the previous record // For non-exact matches, use the time just beyond the end point but don't count that point. if ((dbfData.d_fdata_time[i] == 0.0) || (dbfData.d_fdata_time[i] == dActualEndTime)){ // back up if hit the 0s at end of day dActualEndTime = dbfData.d_fdata_time[i-1]; } else { dActualEndTime = dbfData.d_fdata_time[i]; } ulPtsSoFar = dbfData.ul_fdata_pts_so_far; } // on the end day, find the end time within its multiple record if (StaID.sDataType == DOUBLE_TYPE) { status = FindDbDataRecContainingTime(StaID, dActualEndTime, SEARCH_END, &dbdData); if (status != TRUE) return(status); i = 0; while ((dbdData.d_ddata_time[i] <= dActualEndTime) && (i < (RAW_DATA_RECS_PER_DB_RECORD-1)) && (dbdData.d_ddata_time[i] != 0.0)) { i++; } // find the actual end time. If at the end of the day record (==0) or // have an exact match, then the end time is that of the previous record // For non-exact matches, use the time just beyond the end point but don't count // that point. if ((dbdData.d_ddata_time[i] == 0.0) || (dbdData.d_ddata_time[i] == dActualEndTime)){ // back up if hit the 0s at end of day dActualEndTime = dbdData.d_ddata_time[i-1]; } else { dActualEndTime = dbdData.d_ddata_time[i]; } ulPtsSoFar = dbdData.ul_ddata_pts_so_far; } /* ------------------------------------------------------------------ * Found ending time - calculate how many pts are in day so far * ----------------------------------------------------------------*/ if (bOnlyOneDay) { *pulNumPts = ulPtsSoFar + i - ulPtsInDayBeforeStart; } else { *pulNumPts = *pulNumPts + ulPtsSoFar + i; } *pdActualAdjStartTime = AdjustTimestamp(StaID, dActualStartTime); *pdActualAdjEndTime = AdjustTimestamp(StaID, dActualEndTime); db_exit: return(status); }
// same thing only for doubles data int FindDbDataRecContainingTime(IDStruct StaID,DATE dTime, short sType, struct db_double_data_rec *pdbdData) { struct db_day_rec dbDay; struct db_double_data_rec dbdData; struct db_sta_rec dbDebug; DB_ADDR dba; int db_stat, status; DATE dbBegTime1, dbBegTime2; BOOL bSameDay; short iDbSta; DATE dSearchTime; status = StationExistsInMainDb(StaID.sStaID); if (status != TRUE) return(status); /* ------------------------------------------------------------------ * Check that the day and sSta exist in the db. If dTime falls * after the last time in this day, then move to the next day. Read * out the time associated with the first day record for the day. * ----------------------------------------------------------------*/ dSearchTime = dTime; status = glDbDay.FindDayRecInMainDb(StaID.sStaID, dTime); if (status != TRUE) return (status); // no data for this day in the db // check if the time in question is after the last record in this day db_stat = d_recread(&dbDay, CURR_DB); if (db_stat != S_OKAY) goto db_exit; if (dTime > dbDay.d_day_end_time) { // check that the next day is in the db dSearchTime = floor(dTime); dSearchTime += 1.0; status = glDbDay.FindDayRecInMainDb(StaID.sStaID, dSearchTime); if (status != TRUE) return (status); } if ( d_crread(D_DAY_BEG_TIME_KEY, (char *)&dbBegTime1, CURR_DB)!= S_OKAY) goto db_exit; /* ------------------------------------------------------------------ * There is some data for the day in the db. * Find the key that is just beyond the dTime we are looking for. * ----------------------------------------------------------------*/ // find key closest to search time db_stat = d_keyfind(D_DDATA_BEG_TIME_KEY, &dSearchTime, CURR_DB); if ((db_stat != S_OKAY) && (db_stat != S_NOTFOUND)) goto db_exit; db_stat = d_keynext(D_DDATA_BEG_TIME_KEY, CURR_DB); // go past this key if ((db_stat != S_OKAY) && (db_stat != S_NOTFOUND)) goto db_exit; //read the record as a diagnostic db_stat = d_recread((char*)&dbdData, CURR_DB); //debug /* ------------------------------------------------------------------ * Look through the keys before this one until find one from the requested sSta. * ----------------------------------------------------------------*/ bSameDay = FALSE; do { /* Find the data rec just before the current one and remember its address*/ if (d_keyprev(D_DDATA_BEG_TIME_KEY, CURR_DB) == S_NOTFOUND) break; // no records before db_stat = d_recread((char*)&dbdData, CURR_DB); // debug if (d_crget(&dba, CURR_DB) != S_OKAY) goto db_exit; // save address of data record if (d_findco(DAY_TO_DOUBLE_DATA_SET, CURR_DB) != S_OKAY) goto db_exit; // see who owns this record /* ------------------------------------------------------------------ * Find the day this data rec belongs to. If it is not the same * as the day we're looking for, then have gone back too far. * ----------------------------------------------------------------*/ db_stat = d_recread(&dbDay, CURR_DB); // debug if (d_crread(D_DAY_BEG_TIME_KEY, &dbBegTime2, CURR_DB) != S_OKAY) goto db_exit; bSameDay = SameDay(dbBegTime1, dbBegTime2); // 24-May-2005 use function for SameDay if (!bSameDay) break; /* Find the sSta this day rec belongs to */ if (d_findco(STATION_TO_DAY_SET, CURR_DB) != S_OKAY) goto db_exit; db_stat = d_recread(&dbDebug,CURR_DB); // debug if (d_crread(S_STA_NUM_KEY, &iDbSta, CURR_DB) != S_OKAY) goto db_exit; } while (iDbSta != StaID.sStaID); // is same day but haven't found the station yet so look ahead to see if there // is a record for this day for the desired station if ((bSameDay) && (iDbSta != StaID.sStaID)) { // can this ever be executed?? do { /* Find the data rec just after the current one */ if (d_keynext(D_DDATA_BEG_TIME_KEY, CURR_DB) != S_OKAY) break; db_stat = d_recread((char*)&dbdData, CURR_DB); // debug if (d_crget(&dba, CURR_DB) != S_OKAY) goto db_exit; // save address of data record if (d_findco(DAY_TO_DOUBLE_DATA_SET, CURR_DB) != S_OKAY) goto db_exit; db_stat = d_recread(&dbDay, CURR_DB); // debug /* If this is not the day we're looking for then have gone ahead too far */ if (d_crread(D_DAY_BEG_TIME_KEY, &dbBegTime2, CURR_DB) != S_OKAY) goto db_exit; bSameDay = SameDay(dbBegTime1, dbBegTime2); // 24-May-2005 use function for SameDay if (!bSameDay) { // back up one record if (d_keyprev(D_DDATA_BEG_TIME_KEY, CURR_DB) != S_OKAY) break; break; } /* Find the sSta this day rec belongs to */ if (db_stat = d_findco(STATION_TO_DAY_SET, CURR_DB) != S_OKAY) goto db_exit; db_stat = d_recread(&dbDebug,CURR_DB); // debug if (d_crread(S_STA_NUM_KEY, &iDbSta, CURR_DB) != S_OKAY) goto db_exit; } while ((bSameDay) && (iDbSta != StaID.sStaID)); } // if (!bSameDay) { // went back too far do { /* Find the data rec just after the current one */ if (d_keynext(D_DDATA_BEG_TIME_KEY, CURR_DB) != S_OKAY) break; if (d_crget(&dba, CURR_DB) != S_OKAY) goto db_exit; // save address of data record /* Find the day this data rec belongs to */ if (d_findco(DAY_TO_DOUBLE_DATA_SET, CURR_DB) != S_OKAY) goto db_exit; db_stat = d_recread(&dbDay, CURR_DB); // debug /* If this is not the day we're looking for then have gone ahead too far */ if (d_crread(D_DAY_BEG_TIME_KEY, &dbBegTime2, CURR_DB) != S_OKAY) goto db_exit; bSameDay = SameDay(dbBegTime1, dbBegTime2); // 24-May-2005 use function for SameDay if (!bSameDay) break; /* Find the sSta this day rec belongs to */ if (db_stat = d_findco(STATION_TO_DAY_SET, CURR_DB) != S_OKAY) goto db_exit; db_stat = d_recread(&dbDebug,CURR_DB); // debug if (d_crread(S_STA_NUM_KEY, &iDbSta, CURR_DB) != S_OKAY) goto db_exit; } while (iDbSta != StaID.sStaID); } if (!bSameDay) { return(uiTIME_NOT_IN_DB_STATUS); } /* Found record, restore the address of the last data record found in the key search */ if (d_crset(&dba, CURR_DB) != S_OKAY) goto db_exit; if (StaID.sDataType == DOUBLE_TYPE) // read out record to return db_stat = d_recread((char*)pdbdData, CURR_DB); return(TRUE); db_exit: RadReviewMsg(uiDB_BAD_ERR, "FindDbDataRecContainingTime"); return(uiDB_BAD_ERR); }
/////////////////////////////////////////////////////////////////////////// // Name: GetChannelData // // Description: // Read only x,y data associated with a time interval in the database // where x is the julian time and y is one of the data channels. // The calling routine can specify whether to apply an offset to the x data // so that the time associated with ulStartTime is 0. // // Declaration: // bool CGrandData::GetChannelData(CDbVista *pDb, const int &iChanNuml, const DB_D_INTERVAL &dRequested, DB_D_INTERVAL* pdRequested, CString *pstrErrorMsg) // // Input: pDb pointer to dbVista class for database that should be open for use now // iChanOffset which channel in the data array to read from 1 to 15 (last 8 are status bits) // dRequested requested interval to retrieve data from // // mulNumPtsRequested number of points to read starting at dRequested.dStart // // Output: pdActual actual interval data retrieved from // pstrErrorMsg error msg from problem, if any // // mulNumPtsActual number of points read starting at pdActual->dStart to pdActual->dEnd // mpdXYDataPts ptr to array of mulNumPtsActual CDoubleXYData objects // (user must delete this after use) // mdTimestampOfNextData where to start the search for the data following this interval // // Return: true (data successfully retrieved) / false (some kind of error, see miErrorNum and pstrErroMsg) // // date / author revision // ----------------- -------- // 04-Dec-2001 SFK Created from ReadDbDataArray in DbReadArray.cpp // 07-Feb-2002 SFK For speed reasons, copy data directly into users array - rather // than "newing" an object of appropriate size. // 18-Apr-2002 SFK Changed timebase to DATE // 11-Jun-2002 SFK Changed to actually find the timestamp of the next data point // 14-Oct-2003 SFK Added ability to return the status bits as channesl ////////////////////////////////////////////////////////////////// bool CGrandData::GetChannelData( const int &iChanOffset, const DB_D_INTERVAL &dRequested, DB_D_INTERVAL* pdActual, double *pdTimestamp, double *pdData, CString *pstrErrorMsg) { struct db_float_data_rec dbfData; DB_ADDR dba; DATE dRequestedStartTime, dRequestedEndTime; int i; int db_stat; int iStatus; DATE dCurrentDay, dLastDay; unsigned long j; bool bFinished = false; mulNumPtsActual = 0; pdActual->dStart = 0; pdActual->dEnd = 0; if (pstrErrorMsg) pstrErrorMsg->Empty(); if (mulNumPtsRequested == 0) return(true); if ((iChanOffset < 1) || (iChanOffset > GRAND_NUM_DATA_CHANS)) { if (pstrErrorMsg) pstrErrorMsg->Format("Invalid channel offset requested (channel = %d)\nOnly 1-15 are valid.", iChanOffset); return(false); } dRequestedStartTime = dRequested.dStart; dRequestedEndTime = dRequested.dEnd; /* ------------------------------------------------------------------ * Find the last day in the db for this station, will use later * ----------------------------------------------------------------*/ if (!GetLastTimeInDb(&dLastDay, true)) { if (pstrErrorMsg) pstrErrorMsg->Format("Error in GetLastTimeInDb"); return(false); } /* ------------------------------------------------------------------ * Find the multiple record containing the starting time in the database. * ----------------------------------------------------------------*/ if (!GetMultipleDbRecord(dRequestedStartTime, &i, &dbfData, AFTER)) { if (pstrErrorMsg) pstrErrorMsg->Format("Error in GetMultipleDbRecord"); return(false); } /* ------------------------------------------------------------------ * Get the correct current owner and member set relationships of * the multiple record, so can scan through the records in the day later. * ----------------------------------------------------------------*/ if (d_crget(&dba, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } if (d_findco(DAY_TO_FLOAT_DATA_SET, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } if (d_crset(&dba, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } /* ------------------------------------------------------------------ * Found starting time - transfer data into users struct array * ----------------------------------------------------------------*/ dCurrentDay = dRequestedStartTime; j = 0; int iShifts; long lBit; int iDum; do { do { /* ------------------------------------------------------------------ * If some points are out of order before the start time * asked for, set their time to start time. * ----------------------------------------------------------------*/ if (dbfData.d_fdata_time[i] < dRequestedStartTime) dbfData.d_fdata_time[i] = dRequestedStartTime; if (pdActual->dStart == 0) pdActual->dStart = dbfData.d_fdata_time[i]; // remember time of first point pdActual->dEnd = dbfData.d_fdata_time[i]; // current last time is time of this point //pTemp[j].mdTimestamp = (double)dbfData.ul_fdata_time[i]; pdTimestamp[j] = dbfData.d_fdata_time[i]; /* ------------------------------------------------------------------ * Temporarily, if have points out of order, label them with the * same time as the last time read + 0.001. * ----------------------------------------------------------------*/ // if (j > 0) if (pdTimestamp[j] <= pdTimestamp[j-1]) // pdTimestamp[j] = pdTimestamp[j] + 0.0010; switch (iChanOffset) { case 1: pdData[j] = (double)dbfData.f_data_chan1[i]; break; case 2: pdData[j] = (double)dbfData.f_data_chan2[i]; break; case 3: pdData[j] = (double)dbfData.f_data_chan3[i]; break; case 4: pdData[j] = (double)dbfData.f_data_chan4[i]; break; case 5: pdData[j] = (double)dbfData.f_data_chan5[i]; break; case 6: pdData[j] = (double)dbfData.f_data_chan6[i]; break; case 7: pdData[j] = (double)dbfData.f_data_chan7[i]; break; case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: iShifts = iChanOffset - 8; lBit = 1; lBit = lBit << iShifts; // this is the bit in the status work iDum = dbfData.ul_fdata_status[i] & lBit; if (iDum == lBit) { pdData[j] = 1.0; } else { pdData[j] = .00000001; } break; // 11-Aug-2005 Added cases 16, 17, 18 to support new status bits created during file read case 16: if (dbfData.ul_fdata_status[i] & OFFSET_BIT) { pdData[j] = 1.0; } else { pdData[j] = .00000001; } break; case 17: if (dbfData.ul_fdata_status[i] & INVALID_G_BIT) { pdData[j] = 1.0; } else { pdData[j] = .00000001; } break; case 18: if (dbfData.ul_fdata_status[i] & SATURATED_BIT) { pdData[j] = 1.0; } else { pdData[j] = .00000001; } break; default: pdData[j] = 0; break; } i++; j++; } while ((i<NUM_RAW_DATA_PTS_IN_MULTIPLE_DB_RECORD) && (dbfData.d_fdata_time[i] != 0) && (j != mulNumPtsRequested)); /* ------------------------------------------------------------------ * When have read all the points requested, must figure out the timestamp * of the next point to return. * ----------------------------------------------------------------*/ if (j == mulNumPtsRequested) { // see if can use the next point in this multiple record if ((i < NUM_RAW_DATA_PTS_IN_MULTIPLE_DB_RECORD) && (dbfData.d_fdata_time[i] != 0)) { mdTimestampOfNextData = dbfData.d_fdata_time[i]; // this is the next data point to be readalways update the last time with each point bFinished = true; } else { // must get next record in db and read from it db_stat = d_findnm(DAY_TO_FLOAT_DATA_SET, CURR_DB); if (db_stat == S_EOS) { // see if there is another day in the db if (SameDay(dCurrentDay, dLastDay)) { // no more days in db mulNumPtsActual = j; mdTimestampOfNextData = dbfData.d_fdata_time[i-1]; // best guess available return(true); } do { dCurrentDay += 1.0; iStatus = DayExists(dCurrentDay); } while ((iStatus == iDAY_NOT_IN_DB) && !SameDay(dCurrentDay, dLastDay)); if (iStatus != iDAY_IN_DB) { // there is no more (good) data in the db, use the last time of last record read mulNumPtsActual = j; mdTimestampOfNextData = dbfData.d_fdata_time[i-1]; // best guess available return(true); } // there is another day in the db, get ready to read the first record if (d_setor(DAY_TO_FLOAT_DATA_SET, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } if (d_findfm(DAY_TO_FLOAT_DATA_SET, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } } if (d_recread((char *)&dbfData, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } i = 0; mdTimestampOfNextData = dbfData.d_fdata_time[i]; // this is the next data point to be read bFinished = true; } } /* ------------------------------------------------------------------ * Move on to the next record in this day if it exists, if no * more records in this day, then move on to the next day in the db. * ----------------------------------------------------------------*/ if ((j != mulNumPtsRequested) || !bFinished) { db_stat = d_findnm(DAY_TO_FLOAT_DATA_SET, CURR_DB); if (db_stat == S_EOS) { if (SameDay(dCurrentDay, dLastDay)) { // 06-Jan-2005 if already at last day quite with what we've got mulNumPtsActual = j; mdTimestampOfNextData = dbfData.d_fdata_time[i-1]; // best guess available return(true); } do { dCurrentDay += 1.0; iStatus = DayExists(dCurrentDay);; } while ((iStatus == iDAY_NOT_IN_DB) && !SameDay(dCurrentDay, dLastDay)); if (iStatus != iDAY_IN_DB) { mulNumPtsActual = j; return(true); } if (d_setor(DAY_TO_FLOAT_DATA_SET, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } if (d_findfm(DAY_TO_FLOAT_DATA_SET, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } } else { if (db_stat != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } } if (d_recread((char *)&dbfData, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } i = 0; } } while (j != mulNumPtsRequested); mulNumPtsActual = j; return(true); }
/////////////////////////////////////////////////////////////////////////// // Name: GetStationData // // Description: // Read all Float data associated with a time interval in the database // // Declaration: // bool CGrandData::GetStationData(CDbVista *pDb, const DB_D_INTERVAL &dRequested, CString *pstrErrorMsg) // // Input: dRequested requested interval to retrieve data from // // mulNumPtsRequested number of points to read starting at dRequested.dStart // // Output: pdActual actual interval data retrieved from // pstrErrorMsg error msg from problem, if any // // mulNumPtsActual number of points read starting at pdActual->dStart to pdActual->dEnd // mpWholeFloatDataPts ptr to array of mulNumPtsActual CWholeFloatDbData objects // (user must delete this after use) // m_dTimestampOfNextData where to start the search for the data following this interval // // Return: true (data successfully retrieved) / false (some kind of error, see miErrorNum and pstrErroMsg) // // date / author revision // ----------------- -------- // 04-Dec-2001 SFK Created from ReadDbDataStruct in DbReadStruct.cpp // 18-Apr-2002 SFK Changed timebase to DATE // 11-Jun-2002 SFK Changed to actually find the timestamp of the next data point // 15-Oct-2003 SFK Changed to get the status bits as part of the station record. ////////////////////////////////////////////////////////////////// bool CGrandData::GetStationData(const DB_D_INTERVAL &dRequested, DB_D_INTERVAL* pdActual, CString *pstrErrorMsg) { struct db_float_data_rec dbfData; /* read raw data into here */ DB_ADDR dba; int i; int db_stat; int iStatus; DATE dCurrentDay, dLastDay; unsigned long j; DATE dRequestedStartTime, dRequestedEndTime; bool bFinished = false; mulNumPtsActual = 0; pdActual->dStart = 0; pdActual->dEnd = 0; if (pstrErrorMsg) pstrErrorMsg->Empty(); miErrorNum = 0; if (mulNumPtsRequested == 0) return(true); dRequestedStartTime = dRequested.dStart; dRequestedEndTime = dRequested.dEnd; if (dRequestedEndTime < dRequestedStartTime) { if (pstrErrorMsg) pstrErrorMsg->Format("Requested end time is prior to requested start time."); return(false); } if (dRequestedEndTime == dRequestedStartTime) { if (pstrErrorMsg) pstrErrorMsg->Format("Requested end time is equal to requested start time."); return(false); } /* ------------------------------------------------------------------ * Find the last day in the db for this sSta, will use later * ----------------------------------------------------------------*/ if (!GetLastTimeInDb(&dLastDay, true)) { if (pstrErrorMsg) pstrErrorMsg->Format("Error in GetLastTimeInDb"); return(false); } if (dLastDay < dRequestedStartTime) { if (pstrErrorMsg) pstrErrorMsg->Format("Last day in database is earlier than requested start time."); return(false); } /* ------------------------------------------------------------------ * Find the multiple record containing the starting time in the database. * ----------------------------------------------------------------*/ if (!GetMultipleDbRecord(dRequestedStartTime, &i, &dbfData, AFTER)) { if (pstrErrorMsg) pstrErrorMsg->Format("Error in GetMultipleDbRecord"); return(false); } /* ------------------------------------------------------------------ * Get the correct current owner and member set relationships of * the multiple record, so can scan through the records in the day later. * ----------------------------------------------------------------*/ if (d_crget(&dba, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } if (d_findco(DAY_TO_FLOAT_DATA_SET, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } if (d_crset(&dba, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } /* ------------------------------------------------------------------ * Found starting time - transfer data into users struct array * ----------------------------------------------------------------*/ dCurrentDay = dRequestedStartTime; j = 0; if (mpGrandDataPtArray) delete [] mpGrandDataPtArray; mpGrandDataPtArray = new CGrandDbDataPt[mulNumPtsRequested]; CGrandDbDataPt* pTemp = mpGrandDataPtArray; bool bool1, bool2, bool3; if (pTemp) { do //while (j != mulNumPtsRequested); { do //while (bool1 && bool2 && bool3); { pTemp[j].mdJulianTime = dbfData.d_fdata_time[i]; if (pdActual->dStart == 0) pdActual->dStart = dbfData.d_fdata_time[i]; // remember the first time pdActual->dEnd = dbfData.d_fdata_time[i]; // always update the last time with each point pTemp[j].mulStatus = dbfData.ul_fdata_status[i]; pTemp[j].mfData[0] = dbfData.f_data_chan1[i]; pTemp[j].mfData[1] = dbfData.f_data_chan2[i]; pTemp[j].mfData[2] = dbfData.f_data_chan3[i]; pTemp[j].mfData[3] = dbfData.f_data_chan4[i]; pTemp[j].mfData[4] = dbfData.f_data_chan5[i]; pTemp[j].mfData[5] = dbfData.f_data_chan6[i]; pTemp[j].mfData[6] = dbfData.f_data_chan7[i]; pTemp[j].mfData[7] = 0; pTemp[j].mfData[8] = 0; pTemp[j].mfData[9] = 0; pTemp[j].mfData[10] = 0; pTemp[j].mfData[11] = 0; pTemp[j].mfData[12] = 0; pTemp[j].mfData[13] = 0; pTemp[j].mfData[14] = 0; pTemp[j].mfData[15] = 0; pTemp[j].mfData[16] = 0; pTemp[j].mfData[17] = 0; if (dbfData.ul_fdata_status[i] & BIT_D0) pTemp[j].mfData[7] = 1; // In MII if (dbfData.ul_fdata_status[i] & BIT_D1) pTemp[j].mfData[8] = 1; // No authentication if (dbfData.ul_fdata_status[i] & BIT_D2) pTemp[j].mfData[9] = 1; // Cold start if (dbfData.ul_fdata_status[i] & BIT_D3) pTemp[j].mfData[10] = 1; // Taking offsets if (dbfData.ul_fdata_status[i] & BIT_D4) pTemp[j].mfData[11] = 1; // Over thresholds if (dbfData.ul_fdata_status[i] & BIT_D5) pTemp[j].mfData[12] = 1; // Changing Signal if (dbfData.ul_fdata_status[i] & BIT_D6) pTemp[j].mfData[13] = 1; // Battery low if (dbfData.ul_fdata_status[i] & BIT_D7) pTemp[j].mfData[14] = 1; // AC power loss // 22-Feb-2006 SFK Added setting the values in the last 3 "channels" if (dbfData.ul_fdata_status[i] & BIT_D16) pTemp[j].mfData[15] = 1; // Taking offsets if (dbfData.ul_fdata_status[i] & BIT_D17) pTemp[j].mfData[16] = 1; // Invalid gammas if (dbfData.ul_fdata_status[i] & BIT_D18) pTemp[j].mfData[17] = 1; // Saturated gammas pTemp[j].mdElapsedTime = dbfData.d_fdata_etime[i]; j++; i++; bool1 = (i < NUM_RAW_DATA_PTS_IN_MULTIPLE_DB_RECORD); //78 bool2 = (dbfData.d_fdata_time[i] != 0); bool3 = (j != mulNumPtsRequested); } while (bool1 && bool2 && bool3); /* ------------------------------------------------------------------ * When have read all the points requested, must figure out the timestamp * of the next point to return. * ----------------------------------------------------------------*/ if (j == mulNumPtsRequested) { // see if can use the next point in this multiple record if ((i < NUM_RAW_DATA_PTS_IN_MULTIPLE_DB_RECORD) && (dbfData.d_fdata_time[i] != 0)) { mdTimestampOfNextData = dbfData.d_fdata_time[i]; // this is the next data point to be readalways update the last time with each point bFinished = true; } else { // must get next record in db and read from it db_stat = d_findnm(DAY_TO_FLOAT_DATA_SET, CURR_DB); if (db_stat == S_EOS) { // see if there is another day in the db if (SameDay(dCurrentDay, dLastDay)) { // no more days in db mulNumPtsActual = j; mdTimestampOfNextData = dbfData.d_fdata_time[i-1]; // best guess available return(true); } do { dCurrentDay += 1.0; iStatus = DayExists(dCurrentDay); } while ((iStatus == iDAY_NOT_IN_DB) && !SameDay(dCurrentDay, dLastDay)); if (iStatus != iDAY_IN_DB) { // there is no more (good) data in the db, use the last time of last record read mulNumPtsActual = j; mdTimestampOfNextData = dbfData.d_fdata_time[i-1]; // best guess available return(true); } // there is another day in the db, get ready to read the first record if (d_setor(DAY_TO_FLOAT_DATA_SET, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } if (d_findfm(DAY_TO_FLOAT_DATA_SET, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } } if (d_recread((char *)&dbfData, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } i = 0; mdTimestampOfNextData = dbfData.d_fdata_time[i]; // this is the next data point to be read bFinished = true; } } /* ------------------------------------------------------------------ * Move on to the next record in this day if it exists, if no * more records in this day, then move on to the next day in the db. * ----------------------------------------------------------------*/ if ((j != mulNumPtsRequested) || !bFinished) { if (SameDay(dCurrentDay, dLastDay)) { j = j; } db_stat = d_findnm(DAY_TO_FLOAT_DATA_SET, CURR_DB); if (db_stat == S_EOS) //end of set { if (SameDay(dCurrentDay, dLastDay)) { // 06-Jan-2005 if already at last day quite with what we've got mulNumPtsActual = j; mdTimestampOfNextData = dbfData.d_fdata_time[i-1]; // best guess available return(true); } do { dCurrentDay += 1.0; iStatus = DayExists(dCurrentDay); } while ((iStatus == iDAY_NOT_IN_DB) && !SameDay(dCurrentDay, dLastDay)); //13 if (iStatus != iDAY_IN_DB) //12 { mulNumPtsActual = j; return(true); } if (d_setor(DAY_TO_FLOAT_DATA_SET, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } if (d_findfm(DAY_TO_FLOAT_DATA_SET, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } } if (d_recread((char *)&dbfData, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } i = 0; } } while (j != mulNumPtsRequested); } //if pTemp mulNumPtsActual = j; return(true); }
/////////////////////////////////////////////////////////////////////////// // Name: GetMultipleDbRecord // // Description: // Find the db_data multiple rec containing the specified ulTime. // If the record time does not exactly match the time requested, // then based on the iSnap parameter find either the prior or following // record in the day for the station. // // Special notes: if TRUE, curr_rec = multiple record containing the ulTime // // Declaration: // bool CGrandData::GetMultipleDbRecord(DATE dTime, int* piIndex, struct db_float_data_rec *pdbfData, int iSnap) // // Input: dTime Time looking for in database for msStaNum // iSnap if the exact record is not found, tells which way to move to "snap" to a data record // (either BEFORE or AFTER). // // Output: piIndex which record in "multiple" record matches // pdbfData pointer to "multiple" record from database for msStaNum containing ulTime // // miErrorNum number of error, if any // // Return: true (found record with time) /false // if false then miErrorNum is one of the following // iSTA_NOT_IN_DB msStaNum unknown in database // iDB_BAD dbVista database error // iDAY_NOT_IN_DB no day in database containing ulTime // iDAY_IN_DB day for station msStaNum containing ulTime exists in database // iTIME_NOT_IN_DB can't find any record with ulTime // iTIME_IN_REC dbfData record contains ulTime // // date / author revision // ----------------- -------- // 04-Dec-2001 SFK Created from FindDbDataRecContainingTime in DbInterval.cpp // 18-Apr-2002 SFK Changed timebase to DATE // 06-JAN-2005 SFK Added condition of dSearchTime before record time // 26-APR-2005 SFK Added condition of remembering which way we moved before since the 06-JAN // fix didn't work with another data set. ////////////////////////////////////////////////////////////////// bool CGrandData::GetMultipleDbRecord(DATE dTime, int* piIndex, struct db_float_data_rec *pdbfData, SNAP eSnap) { DB_ADDR dba; bool bdbSuccess = true; bool bSameDay = true; int db_stat; int iStatus; int i; short iDbSta; DATE dBegTime1, dBegTime2; DATE dSearchTime; bool bMovePrev = true; *piIndex = 0; miErrorNum = 0; /* ------------------------------------------------------------------ * Check that the day and sSta exist in the db. If the ulTime falls * after the last ulTime in this day, then move to the next day. Read * out the ulTime associated with the first day record for the day. * ----------------------------------------------------------------*/ if (!StationDataExists()) { // if station doesn't exist, can't do anything miErrorNum = iSTA_NOT_IN_DB; return(false); } iStatus = FindDayContainingClosestRecord(dTime, eSnap, &dSearchTime); if (iStatus != iDAY_IN_DB) { miErrorNum = iStatus; return(false); } // read the beginning time for the day containing our search time if ( d_crread(D_DAY_BEG_TIME_KEY, (char *)&dBegTime1, CURR_DB)!= S_OKAY) goto dbVistaError; // have found the day containing the desired time. // find multiple record key closest to search time db_stat = d_keyfind(D_FDATA_BEG_TIME_KEY, &dSearchTime, CURR_DB); if ((db_stat != S_OKAY) && (db_stat != S_NOTFOUND)) goto dbVistaError; // if this is not an actual key match try to lock onto the previous key // if that fails, then lock onto the next key if (db_stat != S_OKAY) { db_stat = d_keyprev(D_FDATA_BEG_TIME_KEY, CURR_DB); bMovePrev = true; } if (db_stat == S_NOTFOUND) { db_stat = d_keynext(D_FDATA_BEG_TIME_KEY, CURR_DB); bMovePrev = false; } if ((db_stat != S_OKAY) && (db_stat != S_NOTFOUND)) goto dbVistaError; // examine the record locked onto, if this is not in the same day, move forward // to the next key which should be in the correct day db_stat = d_recread((char*)pdbfData, CURR_DB); if (!SameDay(pdbfData->d_fdata_beg_time_key, dSearchTime)) { db_stat = d_keynext(D_FDATA_BEG_TIME_KEY, CURR_DB); bMovePrev = false; if ((db_stat != S_OKAY) && (db_stat != S_NOTFOUND)) goto dbVistaError; } // Locked onto, see if this is the record we are looking for if (db_stat == S_OKAY) { if (d_crget(&dba, CURR_DB) != S_OKAY) goto dbVistaError; // save address of multiple record // get the day record that owns this multiple record if (d_findco(DAY_TO_FLOAT_DATA_SET, CURR_DB) != S_OKAY) goto dbVistaError; // Get the station that owns this day record if (d_findco(STATION_TO_DAY_SET, CURR_DB) != S_OKAY) goto dbVistaError; //db_stat = d_recread(&dbSta,CURR_DB); // debug if (d_crread(S_STA_NUM_KEY, &iDbSta, CURR_DB) != S_OKAY) goto dbVistaError; // read the station number } else { iDbSta = -1; } // we are latched onto a multiple record just after the one that // contains our time, now find the multiple record that belongs to our station while ((iDbSta != msStaNum) && (bMovePrev == true)) { // 26-APR-2005 Added condition of remembering which way we moved before // Find the data rec just before the current one and remember its address if (d_keyprev(D_FDATA_BEG_TIME_KEY, CURR_DB) == S_NOTFOUND) break; // no multiple records before if (d_crget(&dba, CURR_DB) != S_OKAY) goto dbVistaError; // save address of multiple record // get the day record that owns this multiple record and see if this is still in the correct day if (d_findco(DAY_TO_FLOAT_DATA_SET, CURR_DB) != S_OKAY) goto dbVistaError; if (d_crread(D_DAY_BEG_TIME_KEY, &dBegTime2, CURR_DB) != S_OKAY) goto dbVistaError; //beginning time in day //db_stat = d_recread(&dbDay, CURR_DB); // debug // if this is not the day we are looking for, we've gone too far back bSameDay = SameDay(dBegTime1, dBegTime2); if (!bSameDay) break; // Get the station that owns this day record if (d_findco(STATION_TO_DAY_SET, CURR_DB) != S_OKAY) goto dbVistaError; //db_stat = d_recread(&dbSta,CURR_DB); // debug if (d_crread(S_STA_NUM_KEY, &iDbSta, CURR_DB) != S_OKAY) goto dbVistaError; } // if still haven't found the record, look forward until get past the day we know the record has to be in if (iDbSta != msStaNum) { do { /* Find the data rec just after the current one */ if (d_keynext(D_FDATA_BEG_TIME_KEY, CURR_DB) != S_OKAY) break; // no records before //db_stat = d_recread((char*)&dbfData, CURR_DB); // debug if (d_crget(&dba, CURR_DB) != S_OKAY) goto dbVistaError; // save address of data record if (d_findco(DAY_TO_FLOAT_DATA_SET, CURR_DB) != S_OKAY) goto dbVistaError; //db_stat = d_recread(&dbDay, CURR_DB); // debug /* If this is not the day we're looking for then have gone ahead too far */ if (d_crread(D_DAY_BEG_TIME_KEY, &dBegTime2, CURR_DB) != S_OKAY) goto dbVistaError; bSameDay = SameDay(dBegTime1, dBegTime2); if (!bSameDay) break; // if (!bSameDay) { // back up one record // if (d_keyprev(UL_FDATA_BEG_TIME_KEY, CURR_DB) != S_OKAY) break; // } /* Find the sSta this day rec belongs to */ if (db_stat = d_findco(STATION_TO_DAY_SET, CURR_DB) != S_OKAY) goto dbVistaError; //db_stat = d_recread(&dbSta,CURR_DB); // debug if (d_crread(S_STA_NUM_KEY, &iDbSta, CURR_DB) != S_OKAY) goto dbVistaError; } while (iDbSta != msStaNum); } if (!bSameDay) { miErrorNum = iTIME_NOT_IN_DB; return(false); } /* Found record, restore the address of the last data record found in the key search */ if (d_crset(&dba, CURR_DB) != S_OKAY) goto dbVistaError; // return the record with the value if (d_recread((char*)pdbfData, CURR_DB) != S_OKAY) goto dbVistaError; // search through the record and find the value or the point just beyond where the value would be i = 0; while ((pdbfData->d_fdata_time[i] < dTime) && (i < (NUM_RAW_DATA_PTS_IN_MULTIPLE_DB_RECORD-1)) && (pdbfData->d_fdata_time[i] != 0)) { i++; } // when exit this are either at the point or the point beyond where you asked for if (pdbfData->d_fdata_time[i] != dTime) { if ((eSnap == BEFORE) && (i != 0)) i--; } *piIndex = i; return(true); dbVistaError: miErrorNum = iDB_BAD; return(false); }
/////////////////////////////////////////////////////////////////////////// // Name: GetDataStatistics // // Description: // Find the interval in the db. Calculate the number of points // in the database for the specified station and facility during // the requested interval (including endpoints). // // // Declaration: // bool CGrandData::GetDataStatistics(const DB_D_INTERVAL &dRequested, DB_D_INTERVAL *pdActual, CString *pstrErrorMsg) // // Input: dRequested interval to search for // // Output: pdActual interval actually found in db >=dRequested start and <=dRequested end // pstrErrorMsg error message, if any // // miErrorNum number of error, if any // mulNumPtsActual number of data points in the dRequested interval (including endpoints) // // Return: true (all okay) / false (error occurred while trying to determine number of points) // // date / author revision // ----------------- -------- // 03-Dec-2001 SFK Created from FindIntervalInDb in DbInterval.cpp // 18-Apr-2002 SFK Changed timebase to DATE ////////////////////////////////////////////////////////////////// bool CGrandData::GetDataStatistics( const DB_D_INTERVAL &dRequested, DB_D_INTERVAL *pdActual, CString *pstrErrorMsg) { struct db_day_rec dbCurrentDay; // day presently reading struct db_float_data_rec dbfData; // record containing raw float data int i; DATE dCurrentDay; // day you want to find in database in jul secs unsigned long ulPtsInDayBeforeStart; DATE dActualEndTime, dActualStartTime; DATE dRequestedStartTime, dRequestedEndTime; DATE dAdjRequestedStartTime, dAdjRequestedEndTime; unsigned long ulPtsSoFar; bool bOnlyOneDay; bool bDone; mulNumPtsActual = 0; pdActual->dStart = 0.0; pdActual->dEnd = 0.0; if (pstrErrorMsg) pstrErrorMsg->Empty(); miErrorNum = 0; // Check that some data exist for the station in the db if (!StationDataExists()) //This call sets CBaseVistaData::miErrorNum { if (pstrErrorMsg) pstrErrorMsg->Format(" StationDataExists() returns error." ); return false; } dRequestedStartTime = dRequested.dStart; dRequestedEndTime = dRequested.dEnd; // Find the day containing the requested end time (or the day containing the record // just before the end time). miErrorNum = FindDayContainingClosestRecord(dRequestedEndTime, BEFORE, &dAdjRequestedEndTime); if (miErrorNum != iDAY_IN_DB) { if (pstrErrorMsg) pstrErrorMsg->Format(" FindDayContainingClosestEndTime() returns error."); return(false); } // Find the day containing the requested start time (or the day containing the record // just after the start time). miErrorNum = FindDayContainingClosestRecord(dRequestedStartTime, AFTER, &dAdjRequestedStartTime); if (miErrorNum != iDAY_IN_DB) { if (pstrErrorMsg) pstrErrorMsg->Format(" FindDayContainingClosestStartTime() returns error. "); return(false); } ////////////////////////////// MODIFIED FOR NDAR ////////////////////////////// // pjm 12-04-2006 // // Need to rethink this for Baseline 3 because RAD uses the 1-point, times equal // return values. Kelly Michel suggested leaving the adjusted start and end times // in the return for RAD to key off of if the number of points is zero. // This would require a small modification in the RAD logic. // // handle case of one point in day // // Here are the original 7 lines // //if (dAdjRequestedStartTime == dAdjRequestedEndTime) //{ // pdActual->dStart = dAdjRequestedStartTime; // pdActual->dEnd = dAdjRequestedEndTime; // mulNumPtsActual = 1; // return(true); //} // // Here are the new 7 lines // if (dAdjRequestedStartTime == dAdjRequestedEndTime) { pdActual->dStart = dAdjRequestedStartTime; pdActual->dEnd = dAdjRequestedEndTime; mulNumPtsActual = 0; //if (pstrErrorMsg) //{ // pstrErrorMsg->Format("AdjustedRequestedStartTime(%f) == AdjustedRequestedEndTime(%f)", // dAdjRequestedStartTime,dAdjRequestedEndTime); //} return(true); } // //////////////////////END MODIFIED FOR NDAR ////////////////////////////// // these cases should never happen; if they do return 0 points. if ((dRequestedEndTime < dAdjRequestedStartTime) || (dRequestedStartTime > dAdjRequestedEndTime)) { miErrorNum = iNOT_DB_ISSUE; if (pstrErrorMsg) pstrErrorMsg->Format(" Adjustment of requested times error. "); return false; } //ulCurrentDay = ulRequestedStartTime; // get the multiple data record containing the start time. bool bStatus = GetMultipleDbRecord(dAdjRequestedStartTime, &i, &dbfData, AFTER); // read record containing start time if (!bStatus) { if (pstrErrorMsg) pstrErrorMsg->Format(" GetMultipleDbRecord() returns error. "); return(false); } // make this day the owner of the multiple data set to explore if (d_setmr(DAY_TO_FLOAT_DATA_SET, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } if (d_csoread(DAY_TO_FLOAT_DATA_SET, UL_DAY_TOTAL_PTS, (char *)&mulNumPtsActual, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } // figure out how many points to count for the start day if (dbfData.d_fdata_time[i] == 0) if (i != 0) i--; // back up if hit the 0s at end of day as they signal no data ulPtsInDayBeforeStart = dbfData.ul_fdata_pts_so_far + (long)i; mulNumPtsActual = mulNumPtsActual - ulPtsInDayBeforeStart; dActualStartTime = dbfData.d_fdata_time[i]; if (dRequestedEndTime < dActualStartTime) { // once again verify that requested interval is not before any real data in day pdActual->dStart = dRequested.dStart; pdActual->dEnd = dRequested.dEnd; mulNumPtsActual = 0; //miErrorNum = iNOT_DB_ISSUE; // //if (pstrErrorMsg) //{ // pstrErrorMsg->Format("Requested End Time(%f) is before Actual Start Time(%f)", // dRequestedEndTime,dActualStartTime); //} return(true); //return false; //<<QA>>maybe? } // finished with start day, now see if more than one day in the interval bOnlyOneDay = SameDay(dActualStartTime, dAdjRequestedEndTime); // there is more than one day so add the points in each day to the total if (!bOnlyOneDay) { dCurrentDay = dActualStartTime; do { // 09-24-98 rewrite handle case of a missing day dCurrentDay = dCurrentDay + 1.0; // go on to the next day in the db bDone = SameDay(dCurrentDay, dAdjRequestedEndTime); // if is the end day, treat it differently if (!bDone) { // not on the last day int iStatus = DayExists(dCurrentDay); if (iStatus == iDAY_IN_DB) { if (d_recread((char*)&dbCurrentDay, CURR_DB) != S_OKAY) { DbVistaError(pstrErrorMsg, !m_bQuietMode); return(false); } mulNumPtsActual = mulNumPtsActual + dbCurrentDay.ul_day_total_pts; // add the number of pts in this day to the total } } } while (!bDone); } // on the end day, get the multiple record containing the end time bStatus = GetMultipleDbRecord(dAdjRequestedEndTime, &i, &dbfData, BEFORE); if (!bStatus) { if (pstrErrorMsg) pstrErrorMsg->Format("Error in GetMultipleDbRecord"); return(false); } // figure out how many points to count for the end day //hn SR seems to not execute this if no data. Make GRAND consistent. //if (i!=0) // jfl BMEND-125 7/18/2010 But when i is 0, a data point exists, so it is still a necessary point of data, so we DO return the values //{ dActualEndTime = dbfData.d_fdata_time[i]; ulPtsSoFar = dbfData.ul_fdata_pts_so_far; if (bOnlyOneDay) { if ((long)ulPtsInDayBeforeStart - (long)ulPtsSoFar < 0) mulNumPtsActual = 0; // #6: probably the data points are out of order else mulNumPtsActual = ulPtsSoFar + i + 1 - ulPtsInDayBeforeStart; } else { mulNumPtsActual = mulNumPtsActual + ulPtsSoFar + i + 1; } pdActual->dStart = dActualStartTime; pdActual->dEnd = dActualEndTime; //} return(true); }