📄 main.c
字号:
/*===========================================================================*//* DMC interim out| main.c | Main *//*===========================================================================*//* Name: main.c Purpose:make a SEED output volume from a request file Usage: output output-file request-file lrecl precl vol-break ts-break Input: output-file name of file or device to contain SEED data request-file name of file which has the request entries lrecl logical record size (must be 4096) precl physical record size (recommend 32768) vol-break SEED delta time (no ~) of volume-break ts-break SEED delta time (no ~) of timespan break Output: Externals: Warnings: Errors: Fatals: Called by: Calls to: Algorithm: Notes: Problems: known not to work properly if invoked by using zero volume or timespan breaks requires that volume break be a strict multiple of tspan break time. volume start may occur at any multiple of tspan break, not only volume break, if there are holes in the data records. References: Language: Author: 02/??/89 mark wiederspahn Revisions: mm/dd/yy pgmr name change 19aug89 markw change: change Header_path according to the first 6 chars of each request file's superfile. 26oct89 mw bugfix: make sure volume_end is always volume_start plus volume_break. Was not if had empty volume due to holes in data stream time. change: improve messages if find data fails. 10jul90 mw bugfix: add end_tspan arg to find_data call since any channels with a zero sample interval can't figure out their end time otherwise.*/#include <stdlib.h>#include "globals.h"#include "output.h"#define append_linklist_element(new, head, tail) \ new->next = NULL; \ if (head != NULL) tail->next = new; \ else head = new; \ tail = new;struct req_node_type { char station[10]; char net_code[5]; struct req_node_type *next;};void push_req_type();struct req_node_type *req_node_head = NULL;struct req_node_type *req_node_tail = NULL;struct DMC_request request; /* current request */int counter_x = 0;int Process_location_code = 0;int PodJustDoIt = 0;char *Version = "4.2";float User_tolerance;main (argc, argv)int argc;char *argv[];{ char out_dev[PATHLENGTH+1]; /* name of output file/device */ char request_name[PATHLENGTH+1]; /* name of input RDY file */ struct input_time volume_break; /* SEED time (sort of) which contains * the time delta to determine * how logical volumes are split */ struct input_time tspan_break; /* SEED time (sort of) which shows * how timespans are split */ FILE *ifile; /* input file */ FILE *ofile; /* output file */ int nlvol; /* number of nodes in lvol list */ int ntspan; /* number of time spans */ int nread; /* number of request entries read */ int nrequest; /* total number of request entries */ struct input_time start_volume; /* time of volume start */ struct input_time end_volume; /* time of next volume break */ struct input_time end_tspan; /* time of next tspan break */ struct lvol *first; /* first node from find_data call */ char default_header[PATHLENGTH+1]; /* from env HEADER_PATH */ char old_header_path[PATHLENGTH+1];/* previous to this request line */ int was_new_volume; /* 0 if not, <>0 if true */ int is_new_header_path; /* 0 if not, <>0 if true */ int err; int count; char msg[MSGLENGTH+1]; /* debugging msgs */ int l; char *p; int count_xx = 0; if (argc < 7) /* 6 + the command name itself */ { usage(); exit(1); }/* * decipher the argument list */ sscanf( argv[1], "%s", out_dev ); /* the output device or file */ sscanf( argv[2], "%s", request_name ); /* the input file */ sscanf( argv[3], "%d", &Lrecl ); /* the logical record size */ sscanf( argv[4], "%d", &Precl ); /* the physical output size */ volume_break = asc_to_input_time(argv[5]); /* time delta */ tspan_break = asc_to_input_time(argv[6]); /* time delta *//* * decipher the environment: * DEBUG, HEADER_PATH, DATA_PATH, SEED_VERSION, CREATOR */ Write_Data = TRUE; if (getenv("SEEDOUTPUTNODATA") != NULL) Write_Data = FALSE; if (getenv("POD_WITH_LOCID") != NULL) { Process_location_code = TRUE; error_handler(INFO, "[main] POD is processing location codes"); } else { Process_location_code = TRUE; /* always on */ } User_tolerance = 1.0; if ((p = getenv("SEEDTOLERANCE")) != NULL) { if (sscanf(p, "%f", &User_tolerance) == 0) User_tolerance = 1.0; /* default */ } Debug = get_debug_level(); /* recover DEBUG level */ strcpy( Header_path, get_header_path() );/* get where headers are */ strcpy( default_header, Header_path ); /* remember original */ if (Write_Data) Data_path = get_data_path(); /* get where data is */ SEED_Version = get_SEED_version(); /* get what style to write */ strcpy( Organization, get_creator() ); /* name of who is writing */#ifdef MALLOC_DEBUG malloc_debug(2); /* verify every malloc/free */#endif if( Debug >= D_MIN ) fprintf( D_OUT, "[main] start\n" ); if (getenv("PODJUSTDOIT") != NULL) { PodJustDoIt = 1; init_logrec(); make_tspan(&Tspan_head, &Tspan_tail); /* open the output file */ ofile = fopen(out_dev, "a+"); if (ofile == NULL) { error_handler(FATAL, "[main] Unable to open output file!"); perror("pod"); exit(-1); } setbuf(ofile, NULL); /* do not buffer output file */ open_logrec(ofile, Lrecl, Precl, &err); if(err) return(error_handler(FATAL,"[init_once] open_logrec")); podjustdoit(ofile, volume_break, tspan_break); exit(0); } init_find_data(); init_output_data(); /* * do once per program, and once per physical volume initialization * once per output volume initialization is done in the section, * "is_new_volume" */ err = init_once( out_dev, request_name, volume_break, &tspan_break, &ofile, &ifile, &start_volume, &end_volume, &end_tspan, &nrequest ); strcpy( old_header_path, Header_path ); /* remember first */ nread = 0; /* number of request records read */ nlvol = 0; /* number of nodes */ ntspan = 0; /* number of tspans */ err = init_volume( &nlvol, &Lvol_head, &Lvol_tail, &ntspan, &Tspan_head, &Tspan_tail, &Headers_head, &Headers_tail ); (void) set_logrec( ofile, 0 ); /* starting sequence number */ /* * Do for each input request. ASSUME: that we will never ever need * to split a volume or a timespan in the middle of a data series * described by a holdings_file entry (which is what we are * really reading from the request file). This loop will not work * for such cases. */ while(get_DMC_request(ifile, &request ) >= 0 )/* while not eof */ { if( Debug >= D_MIN ) { fprintf( D_OUT, "[main] read %s %s %s\n", request.entry.statn, request.entry.chn, request.entry.start, request.entry.end ); } nread++; if( nread > nrequest ) if( (err=error_handler( WARNING, "[main] request file grew while reading" )) ) exit( 1 ); /* * check whether a new volume should be started. If so, write the * volume we have been generating (if it has anything in it), * and set up for the new volume. */ if( (was_new_volume=is_new_volume( end_volume, request )) ) { if( Debug >= D_MAX ) { fprintf( D_OUT, "[main] from: %.4d,%.3d,%.2d:%.2d:%.2d\n", start_volume.year, start_volume.day, start_volume.hour, start_volume.minute, start_volume.second ); fprintf( D_OUT, "[main] to: %.4d,%.3d,%.2d:%.2d:%.2d\n", end_volume.year, end_volume.day, end_volume.hour, end_volume.minute, end_volume.second ); fprintf( D_OUT, "[main] step: %.4d,%.3d,%.2d:%.2d:%.2d\n", volume_break.year, volume_break.day, volume_break.hour, volume_break.minute, volume_break.second ); fprintf( D_OUT, "[main] ts step: %.4d,%.3d,%.2d:%.2d:%.2d\n", tspan_break.year, tspan_break.day, tspan_break.hour, tspan_break.minute, tspan_break.second ); } err = flush_output_volume( ofile, nlvol, ntspan, volume_break, tspan_break, start_volume, end_volume); err = init_volume( &nlvol, &Lvol_head, &Lvol_tail, &ntspan, &Tspan_head, &Tspan_tail, &Headers_head, &Headers_tail ); (void) set_logrec( ofile, 0 ); /* reset seq no. */ start_volume = end_volume; end_volume = add_inputtime( start_volume, volume_break ); end_tspan = add_inputtime( start_volume, tspan_break ); }/* * this section added (19aug) for multiple header directories, each with its * own private ABBREVIATIONS conventions. This is needed since ASL is sending * abbreviations which are not supersets over time; eg. reusing old numbers * for different strings. This section will apply the current directory * in the first 6 characters to the last 6 characters of the environment * variable HEADER_PATH (which was loaded into program character string * Header_path). Thus, Header_path always contains the proper directory * for this data. WE DO NOT ENFORCE CONSISTENCY AT A VOLUME LEVEL! The * user of this program must assure that changes in the Header names will * always be accompanied by volume breaks; improper SEED will result if * this is not true. An error message will print if we screw up. * * any blank superfiles default to the original value of the environment. */ l = strlen( Header_path ); if( strlen( request.entry.superfile ) != 0 ) { strncpy( Header_path+l-6, request.entry.superfile, 6 ); } else { strcpy( Header_path, default_header ); } is_new_header_path = strcmp( Header_path, old_header_path ); if( Debug >= D_MIN ) { fprintf( D_OUT, "[main] HDR change <%.6s>\n%s\n%s\n%s diff? %d\n", request.entry.superfile, Header_path, old_header_path, default_header, is_new_header_path ); } strcpy( old_header_path, Header_path );/* * if we did not find a volume change with the new header path, * warn the operator. */ if( is_new_header_path && !was_new_volume ) { if( error_handler( FATAL,"[main] New Header_path on same volume" ) ) exit( 1 ); }/* * due to the way we store triggered data, find_data may return 0, 1 or N * nodes per call; these are added to the linked list of lvols. It also * returns the address of the first node it added, which is a candidate * to be the first node in a timespan. We make this decision here. */ err = find_data(&request, end_tspan, &Lvol_head, &Lvol_tail, &Data_path, &count, &first ); if( err ) { sprintf( msg,"[main] find_data failed for file %s code %d", request.entry.file, err ); err=error_handler( ERROR, msg ); }/* * count it (them) in the volume count */ nlvol += count;/* * if we just crossed a timespan break time, make a new timespan, * if we had anything in the old timespan. * In any case, update the next tspan break time; continue * tspans until this data would be within the tspan. There is * no requirement for (and common sense argues against) having * a tspan which has no data. In any case, our logic breaks * if we do allow an empty tspan. Note: init_volume sets * ntspan to 1, since there must be at least one tspan per volume. */ if( is_new_tspan( end_tspan, request ) ) { if( Tspan_tail->count > 0 ) { ntspan++; (void)make_tspan( &Tspan_head, &Tspan_tail ); } while( is_new_tspan( end_tspan, request ) ) { if( ntspan == 1 ) /* if had empty volume */ { start_volume = end_tspan; end_volume = add_inputtime( start_volume, volume_break ); } end_tspan = add_inputtime( end_tspan, tspan_break ); if( Debug >= D_MIN ) { print_time( "start_vol", &start_volume ); print_time( "end_vol", &end_volume ); print_time( "end_tspan", &end_tspan ); } } } /* count the timespan timespan counter. * If the find_data call found the first lvol after a * timespan break, (eg we have none now) then remember it * as the start of the timespan. */ if( Tspan_tail->count == 0 ) Tspan_tail->start = first; Tspan_tail->count += count; } /* while dmc_request */ /* dump_tspans(Tspan_head); */ if( Debug >= D_MAX ) { fprintf( D_OUT, "[main] from: %.4d,%.3d,%.2d:%.2d:%.2d\n", start_volume.year, start_volume.day, start_volume.hour, start_volume.minute, start_volume.second ); fprintf( D_OUT, "[main] to: %.4d,%.3d,%.2d:%.2d:%.2d\n", end_volume.year, end_volume.day, end_volume.hour, end_volume.minute, end_volume.second ); fprintf( D_OUT, "[main] step: %.4d,%.3d,%.2d:%.2d:%.2d\n", volume_break.year, volume_break.day, volume_break.hour, volume_break.minute, volume_break.second ); fprintf( D_OUT, "[main] ts step: %.4d,%.3d,%.2d:%.2d:%.2d\n", tspan_break.year, tspan_break.day, tspan_break.hour, tspan_break.minute, tspan_break.second ); } err = flush_output_volume( ofile, nlvol, ntspan, volume_break, tspan_break, start_volume, end_volume); if( Debug >= D_MIN ) fprintf( D_OUT, "[main] end\n" );/* * write a second file mark ? No. */ printf("POD terminating normally\n"); exit(0);} /* end of program */char *trim_str();/* --------------------------------------------------------------------- * Helper proc */char *trim_str(str)char *str;{ static char x_trim_str[10]; char *p; strncpy(x_trim_str, str, sizeof(x_trim_str)); p = strchr(x_trim_str, ' '); if (p) *p = '\0'; return x_trim_str;}/* ----------------------------------------------------------------------- */struct DMC_request *get_current_request(){ return &request;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -