All Downloads are FREE. Search and download functionalities are using the official Maven repository.

lritdcs.ManualRetransThread Maven / Gradle / Ivy

Go to download

A collection of software for aggregatting and processing environmental data such as from NOAA GOES satellites.

The newest version!
/*
* $Id$
*
* $Log$
* Revision 1.3  2014/05/30 13:15:35  mmaloney
* dev
*
* Revision 1.2  2014/05/28 13:09:31  mmaloney
* dev
*
* Revision 1.1.1.1  2014/05/19 15:28:59  mmaloney
* OPENDCS 6.0 Initial Checkin
*
* Revision 1.3  2009/10/16 12:39:00  mjmaloney
* LRIT updates
*
* Revision 1.2  2009/10/09 18:17:59  mjmaloney
* Added flag bytes and carrier times to LRIT File.
*
* Revision 1.1  2008/04/04 18:21:16  cvs
* Added legacy code to repository
*
* Revision 1.4  2005/12/30 19:41:00  mmaloney
* dev
*
* Revision 1.3  2004/05/21 18:27:45  mjmaloney
* Release prep.
*
* Revision 1.2  2004/05/18 22:52:40  mjmaloney
* dev
*
* Revision 1.1  2004/05/15 22:02:35  mjmaloney
* Implemented retransmit and queue flush features.
*
*/
package lritdcs;

import java.util.*;
import java.io.IOException;
import java.io.File;

import ilex.util.*;
import ilex.cmdline.*;
import lrgs.common.SearchCriteria;
import decodes.datasource.*;
import decodes.decoder.*;
import decodes.db.*;
import decodes.consumer.*;
import decodes.util.*;

/**
 This class handles manual retransmit requests via a separate connection
 to the DDS servers.
*/
public class ManualRetransThread
	extends LritDcsThread
{
	LritDcsFileWriter output;

	/// The data source that is providing raw messages.
	private HotBackupGroup dataSource;

	/// The status object that we update.
	LritDcsStatus myStatus;

	// Local copies of DDS config so I can detect changes:
	String host1, host2, host3;
	int port1, port2, port3;
	String user1, user2, user3;
	boolean reconfigSource;
	int retryPeriod;
	int timeoutPeriod;
	
	/// Could be used in future to pass params to data source;
	Properties rsProps;

	/// Needed by DECODES datasource for init method, but no used here.
	Vector nlVector;

	/// Each request is represented by a search criteria on the queue.
	LinkedList scQueue;

	/// flag allowing UI to cancel when manual queue is flushed.
	public boolean cancelled;

	public ManualRetransThread()
	{
		super("ManualRetransThread");

		output = null;
		
		shutdownFlag = false;
		dataSource = null;
		myStatus = LritDcsMain.instance().getStatus();

		host1 = host2 = host3 = null;
		port1 = port2 = port3 = 16003;
		user1 = user2 = user3 = null;

		rsProps = new Properties();
		rsProps.setProperty("single", "false");  // Multi mode for retrans requests.

		nlVector = new Vector();
		reconfigSource = false;

		retryPeriod = 600;
		timeoutPeriod = 30;

		scQueue = new LinkedList();
	}

	/// Called whenever config has changed from Observer.
	protected void getConfigValues(LritDcsConfig cfg)
	{
		/*
		  Ideally, every manual request should result in a single LRIT file,
		  so we set the limits pretty high, and then flush the output manually
		  when we get the all-done response from the DDS server.
		*/
		output.setMaxMsgs(300);
		output.setMaxFileBytes(20000);
		output.setMaxFileSeconds(600);

		// Note: changes to searchcrits will be auto detected by writers.

		// Check for changes to server list & reconfigure HBG if nec.
		reconfigSource = 
			!TextUtil.strEqual(host1, cfg.getDds1HostName())
		 || port1 != cfg.getDds1Port()
		 || !TextUtil.strEqual(user1, cfg.getDds1UserName())
		 ||	!TextUtil.strEqual(host2, cfg.getDds2HostName())
		 || port2 != cfg.getDds2Port()
		 || !TextUtil.strEqual(user2, cfg.getDds2UserName())
		 ||	!TextUtil.strEqual(host3, cfg.getDds3HostName())
		 || port3 != cfg.getDds3Port()
		 || !TextUtil.strEqual(user3, cfg.getDds3UserName())
		 || retryPeriod != cfg.getDdsRetryPeriod()
		 || timeoutPeriod != cfg.getDdsTimeOut();

		if (reconfigSource)
		{
			host1 = cfg.getDds1HostName();
			port1 = cfg.getDds1Port();
			user1 = cfg.getDds1UserName();
			host2 = cfg.getDds2HostName();
			port2 = cfg.getDds2Port();
			user2 = cfg.getDds2UserName();
			host3 = cfg.getDds3HostName();
			port3 = cfg.getDds3Port();
			user3 = cfg.getDds3UserName();
			retryPeriod = cfg.getDdsRetryPeriod();
			timeoutPeriod = cfg.getDdsTimeOut();
		}
		// Note: the reconfigSource flag will be used in the main thread loop
		// to create a new HotBackupGroup. Don't do it here because of
		// potential sync problems.
	}

	public void init()
		throws InitFailedException
	{
		LritDcsConfig cfg = LritDcsConfig.instance();

		// Initialize the LritDcsFileWriter objects that provide output.
		String dir = cfg.getLritDcsHome() + File.separator + "low";
		output = new LritDcsFileWriter(Constants.LowPri, dir, false);

		// Note - we rely on the GetMessageThread to initialize Decodes DB.

		// Call update at initial time, then register for updates.
		getConfigValues(LritDcsConfig.instance());
		registerForConfigUpdates();
	}

	public synchronized void queueSC(SearchCriteria sc)
	{
		scQueue.addLast(sc);
	}

	private synchronized SearchCriteria getNextSC()
	{
		try { return (SearchCriteria)scQueue.removeFirst(); }
		catch(NoSuchElementException ex)
		{
			return null;
		}
	}

	/**
	  Thread.run method to work the manual requests, one at a time.
	*/
	public void run()
	{
		info(0, "Starting Manual Retransmit Thread");

		try
		{
			while(!shutdownFlag)
			{
				SearchCriteria sc = getNextSC();
				if (sc == null)
				{
					try { sleep(5000L); }
					catch(InterruptedException ex) {}
					continue;
				}

				try 
				{
					initDataSource(sc); 
					info(-Constants.EVT_DATA_SOURCE_ERR,
					  "Initialized data source for manual retransmits.");
				}
				catch(DataSourceInitException ex)
				{
					warning(Constants.EVT_DATA_SOURCE_ERR,
					  "Could not initialize data source for manual retransmit: "
						+ ex + " -- aborted request.");
					try { sleep(10000L); }
					catch (InterruptedException e) {}
					continue;
				}

				processRetransRequest(sc);
			}
		}
		catch(Exception ex)
		{
			failure(Constants.EVT_INTERNAL_ERR,
				"- Unexpected Exception in main loop. Exiting: " + ex);
			ex.printStackTrace(Logger.instance().getLogOutput());
			LritDcsMain.instance().shutdown();
		}

		LritDcsConfig.instance().deleteObserver(this);
	}


	private void processRetransRequest(SearchCriteria sc)
	{
		Logger.instance().info("Manual Retrans Request.");
		cancelled = false;
		while(!cancelled)
		{
			RawMessage rm = null;
			try
			{
				// Retrieve the next raw message from the data source.
				rm = dataSource.getRawMessage();
				if (rm == null)
				{
					info(0, 
				"Data source failed to return message, pausing for 5 seconds.");
					try { sleep(5000L); }
					catch (InterruptedException e) {}
					continue;
				}

				LrgsDataSource cds = 
					(LrgsDataSource)dataSource.getActiveMember();
				myStatus.lastDataSource = cds == null ? "" : cds.getHostName();
			}
			catch(UnknownPlatformException ex)
			{
				// This shouldn't happen, we turned it off in DataSourceExec.
				warning(0, "Data source '" + dataSource.getName() + "': " + ex
					+ " -- skipped");
			}
			catch(DataSourceEndException ex)
			{
				int n = output.getNumMessages();
				info(0, "Retrieved data for manual retransmit request: " + n 
					+ " messages resulted.");
				break;
			}
			catch(DataSourceException ex)
			{
				failure(Constants.EVT_DATA_SOURCE_ERR, 
					"- Error on manual retrans data source '" 
					+ dataSource.getName() + "': " + ex);
				dataSource = null;
			}

			// We now have a raw message. Construct DcpMsgIndex from it.
			myStatus.lastRetrieval = System.currentTimeMillis();
			try
			{
				// note - all messages must pass criteria!
//				byte[] data = rm.getData();
				output.saveMessage(rm.getOrigDcpMsg());
				myStatus.incrementMsgLow();
			}
			catch(IllegalStateException ex)
			{
				warning(0, "Message from platform '"
					+ rm.getMediumId() + "' discarded: " + ex.toString());
			}

			// Check file time ranges.
			output.checkFileTimeRange();
		}
		if (cancelled)
			warning(0, "Manual retransmit request cancelled by user.");

		// Broke out of above loop -- means this request is done!
		output.saveFile();
		dataSource.close();
		dataSource = null;
	}

	// Initialize the data source object.
	protected void initDataSource(SearchCriteria sc)
		throws DataSourceInitException
	{
		debug3("initDataSource(retry=" + retryPeriod +
			", timeout=" + timeoutPeriod + ")");

		LritDcsConfig cfg = LritDcsConfig.instance();
		File f = new File(cfg.getLritDcsHome(), "searchcrit.manual");
		try { sc.saveFile(f); }
		catch(IOException ex)
		{
			String msg = "Cannot save '" + f.getPath() + "': " + ex;
			warning(Constants.EVT_INTERNAL_ERR, msg);
			throw new DataSourceInitException(msg);
		}

		// Initialize the routing spec's data source.
		rsProps.setProperty("recheck", "" + retryPeriod);
		rsProps.setProperty("lrgs.timeout", "" + timeoutPeriod);
		rsProps.setProperty("searchcrit", f.getPath());
		try
		{
			// Construct hot backup group DS with my components.
			DataSource groupDbDs = new DataSource("DdsGroup", "hotbackupgroup");
			int numMembers = 0;

			// Initialize up to 3 DDS connections in the group.
			if (host1 != null && user1 != null)
			{
				DataSource dbds = new DataSource("dds1", "lrgs");
				dbds.setDataSourceArg("hostname=" + host1 + ", "
				+ "port=" + port1 + ", "
				+ "user=" + user1);

				groupDbDs.addGroupMember(numMembers++, dbds);
			}

			if (host2 != null && user2 != null)
			{
				DataSource dbds = new DataSource("dds2", "lrgs");
				dbds.setDataSourceArg("hostname=" + host2 + ", "
				+ "port=" + port2 + ", "
				+ "user=" + user2);

				groupDbDs.addGroupMember(numMembers++, dbds);
			}

			if (host3 != null && user3 != null)
			{
				DataSource dbds = new DataSource("dds3", "lrgs");
				dbds.setDataSourceArg("hostname=" + host3 + ", "
				+ "port=" + port3 + ", "
				+ "user=" + user3);

				groupDbDs.addGroupMember(numMembers++, dbds);
			}

			if (numMembers == 0)
				throw new DataSourceInitException("No data sources specified!");

			/*
			  Retrans requests really SHOULD have a finite time range. If the
			  user didn't provide one, provide defaults of last day here.
			*/
			String s = sc.getLrgsUntil();
			if (s == null || s.trim().length() == 0)
			{
				s = sc.getDapsUntil();
				if (s != null && s.trim().length() > 0)
					sc.setLrgsUntil(s);
				else
					sc.setLrgsUntil("now");
			}
	
			s = sc.getLrgsSince();
			if (s == null || s.trim().length() == 0)
			{
				s = sc.getDapsSince();
				if (s != null && s.trim().length() > 0)
					sc.setLrgsSince(s);
				else
					sc.setLrgsSince("now - 1 day");
			}

			dataSource = (HotBackupGroup)groupDbDs.makeDelegate();
			dataSource.setAllowNullPlatform(true);
			dataSource.setAllowDapsStatusMessages(true);

			dataSource.init(rsProps, sc.getLrgsSince(), sc.getLrgsUntil(), nlVector);
		}
		catch(InvalidDatabaseException ex)
		{
			throw new DataSourceInitException(ex.toString());
		}
		catch(DataSourceException ex)
		{
			throw new DataSourceInitException(ex.toString());
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy