/***************************************************************************** Read a single log file. *****************************************************************************/ void file_read(int fd, short int flnm, char *fnam, FILE *strm, const geoid_height_t *gdhtp, const status_t* status, const cmdlnopts_t *cmdopt) { logfile_t lgfl; #if !defined(FILENAME_DATE_PTR) date_time_t dt; #endif gps_fix_t *gfxp = NULL; float *gcrp = NULL; char *pstr = ""; int fn; if (cmdopt->vflg) printf("Requesting metadata for file %4d\n", flnm); /* Read metadata for file number flnm */ if (get_file_info(fd, flnm, &lgfl) < 0) { fprintf(stderr,"rtkgps: Error reading information for file %d [%s]\n", flnm, gcstrerror(rcerrno)); free(fnam); outlog_enable(fd, status->gpsms, cmdopt); coms_close(fd, cmdopt); exit(5); } /* If memory is allocated for the file name, the output path is a destination directory. Construct a standard file path with the directory as a base, and open the file for writing */ if (fnam != NULL) { #if !defined(FILENAME_DATE_PTR) if (get_file_start_time(fd, &lgfl, &dt) != 1) { fprintf(stderr,"rtkgps: Error reading initial time for file %d [%s]\n", flnm, gcstrerror(rcerrno)); free(fnam); outlog_enable(fd, status->gpsms, cmdopt); coms_close(fd, cmdopt); exit(5); } #endif /* Add filename postfix to indicate file is not complete (data still being captured). */ if (flnm == status->nfile-1) pstr = "_part"; /* Construct file name */ #if defined(FILENAME_DATE_PTR) sprintf(fnam, "%s/%8.8s_%06x%s.%s", cmdopt->dsts, lgfl.date, lgfl.memp, pstr, (cmdopt->nflg)?"rngl":"nmea"); #else sprintf(fnam, "%s/%8.8sT%6.6sZ%s.%s", cmdopt->dsts, lgfl.date, dt.time, pstr, (cmdopt->nflg)?"rngl":"nmea"); #endif /* Skip existing files if requested */ if (cmdopt->uflg && is_nzsregfile(fnam) && flnm != status->nfile-1) { if (cmdopt->vflg) printf("Skipping download for file %4d\n", flnm); return; } /* Create backup of output file if it already exists */ if (file_backup(fnam) != 0) { fprintf(stderr,"rtkgps: Error creating backup of file %s\n", fnam); free(fnam); outlog_enable(fd, status->gpsms, cmdopt); coms_close(fd, cmdopt); exit(3); } /* Attempt to open file */ if ((strm = fopen(fnam, "w")) == NULL) { fprintf(stderr,"rtkgps: Error opening output file %s [%s]\n", fnam, gcstrerror(rcerrno)); free(fnam); outlog_enable(fd, status->gpsms, cmdopt); coms_close(fd, cmdopt); exit(3); } } /* Allocate memory for the log file data */ if ((gfxp = malloc(lgfl.nfix*sizeof(gps_fix_t))) == NULL) { fprintf(stderr,"rtkgps: Error allocating memory\n"); free(fnam); if (fnam != NULL) fclose(strm); outlog_enable(fd, status->gpsms, cmdopt); coms_close(fd, cmdopt); exit(2); } #ifdef GEOIDCOR /* If necessary, allocate memory for geoid correction values */ if (lgfl.fxtyp > 0 && gdhtp->filep != NULL) { if ((gcrp = malloc(lgfl.nfix*sizeof(float))) == NULL) { fprintf(stderr,"rtkgps: Error allocating memory\n"); free(fnam); if (fnam != NULL) fclose(strm); outlog_enable(fd, status->gpsms, cmdopt); coms_close(fd, cmdopt); exit(2); } } #endif if (cmdopt->vflg) printf("Requesting content of file %4d\n", flnm); /* Read the log file data */ fn = get_file_data(fd, &lgfl, gfxp); if (fn < 0) { fprintf(stderr,"rtkgps: Error reading file %d [%s]\n", flnm, gcstrerror(rcerrno)); /* Remove empty file so that it isn't skipped (with -u flag) on read restart */ if (fnam != NULL) remove(fnam); free(gcrp); free(gfxp); free(fnam); if (fnam != NULL) fclose(strm); outlog_enable(fd, status->gpsms, cmdopt); coms_close(fd, cmdopt); exit(5); } #ifdef GEOIDCOR if (gcrp != NULL) { const double dgrd = 360.0/(2*M_PI); unsigned short n; if (cmdopt->vflg) printf("Computing geoid altitude corrections\n"); for (n = 0; n < lgfl.nfix; n++) { gcrp[n] = geoid_calc_correction(gdhtp, dgrd*gfxp[n].lat, dgrd*gfxp[n].lng); } } #endif /* Print the log file data to the output stream */ if (cmdopt->nflg) { if (fnam != NULL) print_hdr_native(strm); print_log_native(strm, &lgfl, gfxp, gcrp); } else { if (fnam != NULL) print_hdr_nmea(strm, cmdopt->btas); print_log_nmea(strm, &lgfl, gfxp, gcrp); } /* Free memory for geoid correction values */ free(gcrp); /* Free memory for the log file data */ free(gfxp); /* If memory is allocated for the file name, the output path is a directory and the output stream was opened in this function, so the stream should be closed here */ if (fnam != NULL) fclose(strm); }
void rotate_files( bool initializing = false ) { FC_ASSERT( cfg.rotate ); fc::time_point now = time_point::now(); fc::time_point_sec start_time = get_file_start_time( now, cfg.rotation_interval ); string timestamp_string = start_time.to_non_delimited_iso_string(); fc::path link_filename = cfg.filename; fc::path log_filename = link_filename.parent_path() / (link_filename.filename().string() + "." + timestamp_string); { fc::scoped_lock<boost::mutex> lock( slock ); if( !initializing ) { if( start_time <= _current_file_start_time ) { _rotation_task = schedule( [this]() { rotate_files(); }, _current_file_start_time + cfg.rotation_interval.to_seconds(), "rotate_files(2)" ); return; } out.flush(); out.close(); } remove_all(link_filename); // on windows, you can't delete the link while the underlying file is opened for writing if( fc::exists( log_filename ) ) out.open( log_filename, std::ios_base::out | std::ios_base::app ); else out.open( log_filename, std::ios_base::out | std::ios_base::app); create_hard_link(log_filename, link_filename); } /* Delete old log files */ fc::time_point limit_time = now - cfg.rotation_limit; string link_filename_string = link_filename.filename().string(); directory_iterator itr(link_filename.parent_path()); for( ; itr != directory_iterator(); itr++ ) { try { string current_filename = itr->filename().string(); if (current_filename.compare(0, link_filename_string.size(), link_filename_string) != 0 || current_filename.size() <= link_filename_string.size() + 1) continue; string current_timestamp_str = current_filename.substr(link_filename_string.size() + 1, timestamp_string.size()); fc::time_point_sec current_timestamp = fc::time_point_sec::from_iso_string( current_timestamp_str ); if( current_timestamp < start_time ) { if( current_timestamp < limit_time || file_size( current_filename ) <= 0 ) { remove_all( *itr ); continue; } } } catch (const fc::canceled_exception&) { throw; } catch( ... ) { } } _current_file_start_time = start_time; _rotation_task = schedule( [this]() { rotate_files(); }, _current_file_start_time + cfg.rotation_interval.to_seconds(), "rotate_files(3)" ); }