Exemple #1
0
static PyObject *
python_orbseek( PyObject *self, PyObject *args ) {
	char	*usage = "Usage: _orbseek(orb, whichpkt)\n";
	int	orbfd;
	int	whichpkt;
	int	pktid;

	if( ! PyArg_ParseTuple( args, "ii", &orbfd, &whichpkt ) ) {

		if( ! PyErr_Occurred() ) {

			PyErr_SetString( PyExc_RuntimeError, usage );
		}

		return NULL;
	}

	pktid = orbseek( orbfd, whichpkt );

	return Py_BuildValue( "i", pktid );
}
int
main( int argc, char **argv )
{
	int	c;
	int	errflag = 0;
	int	orb;
	int	stop = 0;
	long	nrecs;
	char	*match = ".*/pf/st";
	char	*from = 0;
	char	*statefile = 0;
	char	*pfname = "orb2rrdc";
	char	*orbname;
	char	*dbcache;
	char	*rrdtool;
	char	command[STRSZ];
	char	net[STRSZ];
	char	sta[STRSZ];
	char	rrdvar[STRSZ];
	char	key[STRSZ];
	char	path[FILENAME_MAX];
	Dbptr	db;
	Dbptr	dbt;
	Pf	*pf;
	char	*Default_network;
	Tbl	*dlslines;
	Arr	*Dls_vars_dsparams;
	Arr	*Dls_vars_rras;
	Tbl	*Dls_vars_keys;
	char	*line;
	char	*dls_var;
	char	*dsparams;
	Tbl	*rras;
	int	i;
	int	j;
	OrbreapThr *ort;
	int	pktid;
	char	srcname[ORBSRCNAME_SIZE];
	double	time = 0;
	char	*packet = 0;
	int	nbytes = 0;
	int	bufsize = 0;
	Packet	*pkt = 0;
	int	rc;
	char	*s;
	Pf	*dlspf;
	Tbl	*dlspfkeys;
	char	*element;
	Tbl	*parts;
	double	val;
	Pf	*pfval = 0;

	elog_init( argc, argv );

	while( ( c = getopt( argc, argv, "vVd:s:p:m:f:" ) ) != -1 ) {

		switch( c ) {

		case 'd':
			CacheDaemon = optarg;
			break;

		case 'f':
			from = optarg;
			break;

		case 'm':
			match = optarg;
			break;

		case 'p': 
			pfname = optarg;
			break;

		case 's':
			statefile = optarg;
			break;
			
		case 'v':
			Verbose++;
			break;

		case 'V':
			VeryVerbose++;
			Verbose++;
			break;
		
		default:
			elog_complain( 0, "Unknown option '%c'\n", c );
			errflag++;
			break;
		}
	}

	if( errflag || argc - optind != 2 ) {

		usage();
	}

	if( Verbose ) {

		elog_notify( 0, "Starting at %s (%s $Revision$ $Date$)\n", 
				zepoch2str( str2epoch( "now" ), "%D %T %Z", "" ),
				Program_Name );
	}

	orbname = argv[optind++];
	dbcache = argv[optind++];

	pfread( pfname, &pf );

	rrdtool = pfget_string( pf, "rrdtool" );

	if( rrdtool == NULL || ! strcmp( rrdtool, "" ) ) {

		elog_die( 0, "Error: no rrdtool executable name specified in parameter file\n" );

	} else if( ( rrdtool[0] == '/' && ! is_present( rrdtool ) ) || ( rrdtool[0] != '/' && ! datafile( "PATH", rrdtool ) ) ) {

		elog_die( 0, "Error: can't find rrdtool executable by name of '%s' (check PATH environment " 
			"variable, or absolute path name if given)\n", rrdtool );

	} else if( rrdtool[0] == '/' ) {

		sprintf( command, "%s -", rrdtool );

	} else {

		sprintf( command, "rrdtool -" );
	}

	Suppress_egrep = pfget_string( pf, "suppress_egrep" );

	if( Suppress_egrep != NULL && strcmp( Suppress_egrep, "" ) ) {
		
		if( ! datafile( "PATH", "egrep" ) ) {

			elog_complain( 0, "Ignoring suppress_egrep parameter: can't find egrep on path\n" ); 

		} else {

			sprintf( command, "%s 2>&1 | egrep -v '%s'", command, Suppress_egrep );
		}
	}

	if( VeryVerbose ) {

		elog_notify( 0, "Executing command: %s\n", command );
	}

	Rrdfp = popen( command, "w" );

	if( Rrdfp == (FILE *) NULL ) {

		elog_die( 0, "Failed to open socket to rrdtool command\n" );
	}

	orb = orbopen( orbname, "r&" );

	if( orb < 0 ) {

		elog_die( 0, "Failed to open orb '%s' for reading. Bye.\n", orbname );
	}

	orbselect( orb, match );

	if( from != NULL && statefile == NULL ) {

		pktid = orbposition( orb, from );

		if( Verbose ) {

			elog_notify( 0, "Positioned to packet %d\n", pktid );
		}

	} else if( from != NULL ) {

		elog_complain( 0, "Ignoring -f in favor of existing state file\n" );
	}

	if( statefile != NULL ) {

		stop = 0;

		exhume( statefile, &stop, 15, 0 );

		orbresurrect( orb, &pktid, &time );

		if( Verbose ) {

			elog_notify( 0, "Resurrecting state to pktid %d, time %s\n",
				pktid, s = strtime( time ) );

			free( s );
		}

		orbseek( orb, pktid );
	}

	dbopen( dbcache, "r+", &db );

	if( db.database < 0 ) {
		
		elog_die( 0, "Failed to open cache database '%s'. Bye.\n", dbcache );

	} else {
		
		db = dblookup( db, "", "rrdcache", "", "" );

		if( db.table < 0 ) {

			elog_die( 0, "Failed to lookup 'rrdcache' table in '%s'. Bye.\n", dbcache );
		}
	}

	dbcrunch( db );

	dbt = dbsubset( db, "endtime == NULL", NULL );

	Rrd_files = newarr( 0 );

	dbquery( dbt, dbRECORD_COUNT, &nrecs );

	for( dbt.record = 0; dbt.record < nrecs; dbt.record++ ) {

		dbgetv( dbt, 0, "net", &net, "sta", &sta, "rrdvar", &rrdvar, NULL );

		dbfilename( dbt, (char *) &path );

		sprintf( key, "%s:%s:%s", net, sta, rrdvar );

		if( ! is_present( path ) ) {
			
			elog_complain( 0, "WARNING: rrd file '%s', listed in database, does not exist. "
				"Removing database entry.\n", path );

			dbmark( dbt );

		} else {

			setarr( Rrd_files, key, strdup( path ) );

			if( VeryVerbose ) {

				elog_notify( 0, "Re-using rrd file '%s' for '%s'\n", path, key );
			}
		}
	}

	Rrdfile_pattern = pfget_string( pf, "rrdfile_pattern" );
	Status_stepsize_sec = pfget_double( pf, "status_stepsize_sec" );
	Default_network = pfget_string( pf, "default_network" );
	dlslines = pfget_tbl( pf, "dls_vars" );

	Dls_vars_dsparams = newarr( 0 );
	Dls_vars_rras = newarr( 0 );

	for( i = 0; i < maxtbl( dlslines ); i++ ) {
		
		line = gettbl( dlslines, i );
		
		strtr( line, "\t", " " );
		rras = split( line, ' ' );

		dls_var = shifttbl( rras );
		dsparams = shifttbl( rras );

		setarr( Dls_vars_dsparams, dls_var, dsparams );
		setarr( Dls_vars_rras, dls_var, rras );
	}

	ort = orbreapthr_new( orb, -1., 0 );

	for( ; stop == 0; ) {

		orbreapthr_get( ort, &pktid, srcname, &time, &packet, &nbytes, &bufsize );

		if( statefile ) {

			rc = bury();

			if( rc < 0 ) {

				elog_complain( 0, "Unexpected failure of bury command! " 
					"(are there two orb2rrdc's running with the same state" 
					"file?)\n" );

				clear_register( 1 );
			}
		}

		rc = unstuffPkt( srcname, time, packet, nbytes, &pkt );

		if( rc == Pkt_pf ) {

			if( VeryVerbose ) {

				/* Parameter files generally too big for elog */

				fprintf( stderr, "Received a parameter-file '%s' at %s\n%s\n\n", 
						srcname, 
						s = strtime( time ), 
						pf2string( pkt->pf ) );

				free( s );

			} else if( Verbose ) {

				elog_notify( 0, "Received a parameter-file '%s' at %s\n", 
						srcname, s = strtime( time ) );

				free( s );
			}

			pfmorph( pkt->pf );

			if( VeryVerbose ) {

				fprintf( stderr, "Morphed parameter-file '%s' to interpret 'opt':\n%s\n\n", 
						srcname, 
						pf2string( pkt->pf ) );
			}

			pfget( pkt->pf, "dls", (void **) &dlspf );

			dlspfkeys = pfkeys( dlspf );
			Dls_vars_keys = keysarr( Dls_vars_dsparams );

			for( i = 0; i < maxtbl( dlspfkeys ); i++ ) {
			   
			   element = gettbl( dlspfkeys, i );

			   if( strcontains( element, "_", 0, 0, 0 ) ) {

				parts = split( (s = strdup( element )), '_' );

				sprintf( net, "%s", (char *) gettbl( parts, 0 ) );
				sprintf( sta, "%s", (char *) gettbl( parts, 1 ) );

				free( s );
				freetbl( parts, 0 );

			   } else {

				sprintf( net, "%s", Default_network );

				sprintf( sta, "%s", element );
			   }

			   for( j = 0; j < maxtbl( Dls_vars_keys ); j++ ) {

			   	dls_var = gettbl( Dls_vars_keys, j );

				sprintf( key, "%s{%s}", element, dls_var );

				if( pfresolve( dlspf, key, 0, &pfval ) < 0 ) {

					elog_complain( 0, "Unable to extract variable '%s' "
						"(not present or wrong type) from element '%s' "
						"in packet from '%s', timestamped '%s'; Skipping\n",
						key, element, srcname, s = strtime( time ) );

					free( s );

					pfval = 0;

					continue;

				} else if( pfval != (Pf *) NULL &&
					   pfval->value.s != (char *) NULL &&
					   ! strcmp( pfval->value.s, "-" ) ) {

					if( VeryVerbose ) {

						elog_notify( 0, "Non-floating point value '-' in variable '%s', "
							"in packet from '%s', timestamped '%s'; Skipping data point\n",
							key, srcname, s = strtime( time ) );

						free( s );
					}

					continue;

				} else {

					val = pfget_double( dlspf, key );
				}

				archive_dlsvar( db, net, sta, dls_var, 
						(char *) getarr( Dls_vars_dsparams, dls_var ),
						(Tbl *) getarr( Dls_vars_rras, dls_var ),
						time, val );
			   }

			}

			freetbl( dlspfkeys, 0 );
			freetbl( Dls_vars_keys, 0 );

		} else if( rc == Pkt_stash ) {

			; /* Do nothing */

		} else {

			if( Verbose ) {

				elog_notify( 0, "Received a packet that's not a parameter file " 
					"(type '%d' from unstuffPkt); skipping\n", rc );
			}
		}
	}
}
int main (int argc, char **argv)
{
	Dbptr master_db, dbtmp;
	char dbname[512];  /* dbtmp name assigned by maketmpdb */
	char *orbname;
	char *pffile=NULL;

	Pf *pf;  /* Input pf object handle */
	Arr *arr_sta;
	Arr *arr_a;  /*Array object associative array -- purely a place holder*/
	Arr *arr_phase;
	int i;
	char *statefile=NULL;
	Point origin;

	int orbin,orbout;  /* We establish both a read and write connection
				on seperate sockets so we can use orbreap on
				the input */
	int quit=0,last_pktid;
	double last_pkttime;
	int exhume_rcode;  /* value returned by exhume*/
	char *packet=0;
	int orid_used;
	Location_options o;
	RTlocate_Options rt_opts;
	ORB_Hypocenter hyp;

	
	/* This initialization is necessary for the orb_arrivals_in routine
	to work correctly on the first pass*/
	hyp.assocs = NULL;

	elog_init(argc, argv);
	elog_notify (0, "$Revision$ $Date$") ;
	if(argc < 2) usage(argv[0]);
	orbname = argv[1];

	for(i=2;i<argc;++i)
	{
		if(!strcmp(argv[i],"-pf"))
		{
			++i;
			pffile = argv[i];
		}
		else if(!strcmp(argv[i],"-S"))
		{
			++i;
			statefile = argv[i];
		}
		else
		{
/* For this kind of program it seems wise to make it a fatal error to 
have the arguments botched */
			elog_complain(0,"Unrecognized argument %s\n",argv[i]);
			usage(argv[0]);
		}
	}
        /* set default this way*/
        if(pffile == NULL) pffile = strdup(DEFAULT_PFFILE);
	if(statefile == NULL) statefile = strdup(DEFAULT_STATEFILE);

	/* parse parameter file and form all the genloc control and
	internal static data structures */
	i = pfread(pffile,&pf);
	if(i != 0) elog_die(1,"Pfread error\n");
	o = parse_options_pf (pf);
	arr_sta = load_station_table(pf);
	arr_a = load_array_table(pf);
 	arr_phase = parse_phase_parameter_file(pf);
	/* Note this is a slightly different use of these variables
	than that used by other genloc routines.  Here we use it
	like a coordinate system origin to select range of distances
	to use. We actually reset these again in the location function,
	but check them here to make sure these variables are in the
	parameter space.  pfget_double will cause the program to die
	if these aren't defined.*/
	origin.lat = pfget_double(pf,"center_latitude");
	origin.lon = pfget_double(pf,"center_longitude");
	origin.z = 0.0;

	rt_opts = parse_rt_options(pf);

	if(dbopen(rt_opts.work_db,"r+",&master_db ) == dbINVALID)
                elog_die(1,"Unable to open master database %s\n",
			rt_opts.work_db);


	/* Now we open the orb server connections */
	if( (orbin=orbopen(orbname,"r&")) < 0)
		elog_die(0,"Cannot open ring buffer %s for reading\n",orbname);
	
	if(orbselect(orbin,"/db/event|/db/origin|/db/assoc|/db/arrival") < 0)
		elog_die(0,"Cannot select any db records from ring buffer %s\n",
			orbname);

	/* These are the state saving routines.  quit is set nonzero 
	whenever the program catches a signal.  We call bury below when
	this happens.  exhume_state is a function because I expect
	it could be used again  */

	exhume_rcode = exhume ( statefile, 0, 0, 0 );
	exhume_state(exhume_rcode);  
        if ( orbresurrect ( orbin, &last_pktid, &last_pkttime ) == 0 )
		elog_complain( 0, "resurrection successful: repositioned to pktid #%d\n", last_pktid ) ;
        else
	{
		orbseek (orbin, ORBOLDEST);
		last_pktid = orbtell(orbin);
		elog_complain( 0, "resurrection unsuccessful\nStarting at beginning of current orb at packet id %d\n",last_pktid ) ;
	}
	/* The following is basically a trick to create a db pointer that
	never references any tables.  This is the preferred approach for
	orbpkt2db records which utilize the scratch record of this database
	pointer.  The fact that we destroy the file this creates turns
	out to be a feature of datascope we can exploit here.  */
	if (maketmpdb ("css3.0", &dbtmp, dbname) < 0) {
		elog_complain(0, "maketmpdb() error.\n");
		exit (1);
	}
	/* This little routine initilizes the null record for each table 
	used here.  This was necessary because we assemble records in the
	scratch record.  This sets proper nulls in fields that are not
	referenced by this program. */
	if(initialize_scratch_records(dbtmp) == dbINVALID)
		elog_complain(0,"Warning:  errors initializing null records in tables.  May generate invalid data in some fields\n");
/*
	unlink (dbname);
*/
	

	if( (orbout=orbopen(orbname,"w&")) < 0)
		elog_die(0,"Cannot open ring buffer %s for writing\n",orbname);

	/* This loop is broken only by an error.  We call bury after each 
	event is processed saving the current packet id.  This should 
	effectively skip events that cause orbgenloc to die for some
	reason. */
	while(1) 
	{
		int return_code;

		return_code = orb_arrivals_in(orbin, dbtmp, &hyp, 
			&last_pktid,rt_opts);
		if(return_code)
		{
		    if(return_code < 0)
			elog_complain(0,"Error reading db records from orb\nCurrent event skipped\n");
		    else
			elog_complain(0,"Sequencing error reading db packets from orbassoc.\nOne or more events were probably skipped\n");
		    continue;
		}
		if(bury())
			elog_complain(0,
			  "bury failed writing statefile %s\n",statefile);

		compute_location(o,rt_opts,arr_sta,arr_a,arr_phase,
				pf,master_db, dbtmp, hyp, orbout);

		/* when last_pktid is -1 orb_arrivals_in does not do 
		an orbseek, so we always reset it here */
		last_pktid = -1;
		/* This is the only appropriate place to release
		this space.  This block is malloced in orb_arrivals_in*/
		free(hyp.assocs);
		hyp.assocs = NULL;
	}
}
/* Input routine for db records for orbgenloc.  

Arguments:
orb - input orb 
dbtmp - temporary database used by orbpkt2db
hyp - returned data structure (see orbgenloc.h)
last_pktid - if nonzero, call orbseek to start at that location
opt - orbgenloc control structure (see orbgenloc.h)


Returns:

-1 = error, data returned is invalid
0 = aok
1 = inconsistency error.  Data are certainly incomplete and should
be ignored.

IMPORTANT:  this routine mallocs a single block of memory to 
hold the hyp->assocs structure.  This MUST be freed externally.

*/
int
orb_arrivals_in (int orb, Dbptr dbtmp, ORB_Hypocenter *hyp, 
int *last_pktid, RTlocate_Options opt)

{
	int pktid, nbytes, bufsize=0;
	char *packet=NULL;
	char srcname[64];
	double time;
	Dbptr db;
	char *table_name;
	int evid, orid, arid, prefor;
	char auth[64];
	int n;
	int number_skipped;

	if (*last_pktid > -1) orbseek (orb, *last_pktid);

	/* The algorithm here is to the following sequence:
	(1)  hunt for a db packet that is an event record.
	(2)  if the event record is auth=orbassoc, start processing, otherwise
	     ignore it.
	(3)  next hunt for an origin record from orbassoc skipping any
	     other embedded origin records (needed in case other locators 
	     are running)
	(4)  Then grab interleaved assoc->arrival rows.  The algorithm 
	     is smart and hunts for an arrival that matches the arid 
	     of the previous assoc record skipping any other db records
	     that do not match.  

	Important assumptions of this are that only one process is emitting
	assoc records into the orb. In addition, this program will block
	and wait forever if an error causes a missing arrival row to never
	appear that has an arid matching a previous output assoc row.  
	We may need a timeout or skip count parameter to avoid this
	potential pitfall.  
	*/

	/* This loop is part (1) of the algorithm */
	while (1) {
		if(orbreap (orb, &pktid, srcname, &time, 
					&packet, &nbytes, &bufsize)) 
		{
			elog_log(0,"orbreap error at packet id %d\nContinuing\n",pktid);
			continue;
		}
		if (strncmp(srcname, "/db/", 4)) continue;
		db = orbpkt2db (packet, nbytes, dbtmp);
		dbquery (db, dbTABLE_NAME, &table_name);
		if (strcmp(table_name, "event")) continue;
		if (dbgetv (db, 0,
				"auth", hyp->auth,
				"evid", &(hyp->evid),
				"prefor", &prefor,
				0) == dbINVALID) {
			elog_log(0, "orbin: dbgetv() error.\n");
			return (-1);
		}
		if (strcmp(hyp->auth, "orbassoc")) continue;
		*last_pktid = pktid;

		/* This is part (2) */
		while (1) {
			orbreap (orb, &pktid, srcname, &time, 
					&packet, &nbytes, &bufsize);
			if (strncmp(srcname, "/db/", 4)) continue;
			db = orbpkt2db (packet, nbytes, dbtmp);
			dbquery (db, dbTABLE_NAME, &table_name);
			if (strcmp(table_name, "origin")) continue;
			if (dbgetv (db, 0,
					"auth", auth,
					"evid", &evid,
					"orid", &(hyp->orid),
					"nass", &(hyp->nass),
					"ndef", &(hyp->ndef),
					"time", &(hyp->time),
					"lat", &(hyp->lat),
					"lon", &(hyp->lon),
					"depth", &(hyp->depth),
					0) == dbINVALID) {
				elog_log(0, "orbin: dbgetv() error.\n");
				return (-1);
			}
			if (strcmp(auth, "orbassoc")) continue;
			if (evid != hyp->evid) continue;
			if (prefor > 0 && prefor != hyp->orid) continue;
			if (hyp->assocs == NULL || hyp->nass > hyp->assocs_size) {
				if (hyp->assocs) free (hyp->assocs);
				hyp->assocs = (Association *) malloc (hyp->nass*sizeof(Association));
				if (hyp->assocs == NULL) {
					elog_log(1, "orbin: malloc() error.\n");
					return (-1);
				}
				hyp->assocs_size = hyp->nass;
			}

			/* This is parts (3) and (4) for assoc->arrival */
			n = 0;
			while (1) {
				orbreap (orb, &pktid, srcname, &time, 
						&packet, &nbytes, &bufsize);
				if (strncmp(srcname, "/db/", 4)) continue;
				db = orbpkt2db (packet, nbytes, dbtmp);
				dbquery (db, dbTABLE_NAME, &table_name);
				if (strcmp(table_name, "assoc")) continue;
				if (dbgetv (db, 0,
						"orid", &orid,
						"arid", &(hyp->assocs[n].arid),
						"delta", &(hyp->assocs[n].delta),
						"seaz", &(hyp->assocs[n].seaz),
						"esaz", &(hyp->assocs[n].esaz),
						"timeres", &(hyp->assocs[n].timeres),
						"timedef", hyp->assocs[n].timedef,
						0) == dbINVALID) {
					elog_log(0, "orbin: dbgetv() error.\n");
					return (-1);
				}
				if (orid != hyp->orid) continue;
				/* This is the safe code to avoid an infinite loop */
				number_skipped = 0;
				while (number_skipped <= opt.db_record_skip_timeout) {
					orbreap (orb, &pktid, srcname, &time, 
							&packet, &nbytes, &bufsize);
					if (strncmp(srcname, "/db/", 4)) continue;
					db = orbpkt2db (packet, nbytes, dbtmp);
					dbquery (db, dbTABLE_NAME, &table_name);
					if (strcmp(table_name, "arrival")) 
					{
						++number_skipped;
						continue;
					}
					if (dbgetv (db, 0,
							"arid", &arid,
							"time", &(hyp->assocs[n].time),
							"sta", hyp->assocs[n].sta,
							"chan", hyp->assocs[n].chan,
							"iphase", hyp->assocs[n].iphase,
							0) == dbINVALID) {
						elog_log(0, "orbin: dbgetv() error.\n");
						return (-1);
					}
					if (arid == hyp->assocs[n].arid) break;
				}
				if(number_skipped >= opt.db_record_skip_timeout) 
				{
					elog_log(0,"Record skipping limit reached while hunting for arrival row to match assoc row.\nResynching\nOne or more events were probably skipped\n");
					return(1);
				}
				n++; 
				if (n >= hyp->nass) break;
			}
			return (0);
		}
	}
}