Commit d80677c5 authored by whitlocb's avatar whitlocb

I made it possible to run the engine and have the engine reverse launch

the viewer and cli so we have more debugging flexibility. This opens the door
to some other possibilities too for making VisIt more batch friendly in 
movie-making mode.



git-svn-id: http://visit.ilight.com/svn/visit/trunk/src@6841 18c085ea-50e0-402c-830e-de6fd14e8384
parent 5dc842c9
......@@ -1025,6 +1025,46 @@ RemoteProcess::MultiThreadedAcceptSocket()
#endif
}
// ****************************************************************************
// Method: RemoteProcess::Launch
//
// Purpose:
// Launches the remote process.
//
// Arguments:
// rHost : The host where the program will be launched.
// createAsThoughLocal : Whether to create the program as local.
// commandLine :
//
// Returns:
//
// Note: I moved this out from the Open method.
//
// Programmer: Brad Whitlock
// Creation: Thu Apr 9 10:25:24 PDT 2009
//
// Modifications:
//
// ****************************************************************************
void
RemoteProcess::Launch(const std::string &rHost, bool createAsThoughLocal,
const stringVector &commandLine)
{
const char *mName = "RemoteProcess::Launch: ";
if (HostIsLocal(rHost) || createAsThoughLocal)
{
debug5 << mName << "Calling LaunchLocal" << endl;
LaunchLocal(commandLine);
}
else
{
debug5 << mName << "Calling LaunchRemote" << endl;
LaunchRemote(commandLine);
}
}
// ****************************************************************************
// Method: RemoteProcess::Open
//
......@@ -1089,6 +1129,9 @@ RemoteProcess::MultiThreadedAcceptSocket()
// Jeremy Meredith, Thu May 24 11:10:15 EDT 2007
// Added SSH tunneling argument; pass it along to CreateCommandLine.
//
// Brad Whitlock, Thu Apr 9 10:40:08 PDT 2009
// I moved some code to the new Launch method.
//
// ****************************************************************************
bool
......@@ -1145,16 +1188,7 @@ RemoteProcess::Open(const std::string &rHost,
//
// Launch the remote process.
//
if (HostIsLocal(rHost) || createAsThoughLocal)
{
debug5 << mName << "Calling LaunchLocal" << endl;
LaunchLocal(commandLine);
}
else
{
debug5 << mName << "Calling LaunchRemote" << endl;
LaunchRemote(commandLine);
}
Launch(rHost, createAsThoughLocal, commandLine);
childDied[GetProcessId()] = false;
......
......@@ -165,6 +165,8 @@ protected:
bool manualSSHPort,
int sshPort, bool useTunneling,
int numRead, int numWrite, bool local);
virtual void Launch(const std::string &rHost, bool createAsThoughLocal,
const stringVector &commandLine);
protected:
int listenPortNum;
std::string localHost, localUserName;
......
This diff is collapsed.
......@@ -75,13 +75,14 @@ class MPIXfer;
class NetworkManager;
class NonBlockingRPC;
class Observer;
class ParentProcess;
class ProcessAttributes;
class ViewerRemoteProcess;
class VisItDisplay;
class Xfer;
#include <vector>
#include <avtDataObjectWriter.h>
#include <ParentProcess.h>
#include <BufferConnection.h>
#include <SaveWindowAttributes.h>
......@@ -200,6 +201,9 @@ class Xfer;
// I changed the command callback mechanism so it only accepts string
// arguments and it also accepts user-provided callback data.
//
// Brad Whitlock, Thu Apr 9 11:55:50 PDT 2009
// I made it possible to reverse launch the viewer.
//
// ****************************************************************************
class Engine
......@@ -275,6 +279,8 @@ class Engine
protected:
Engine();
void ProcessCommandLine(int argc, char *argv[]);
bool ReverseLaunchViewer(int *argc, char **argv[]);
void ExtractViewerArguments(int *argc, char **argv[]);
static void AlarmHandler(int signal);
static void NewHandler(void);
......@@ -284,10 +290,13 @@ class Engine
protected:
// The singleton object
static Engine *instance;
static Engine *instance;
// The Viewer
ParentProcess theViewer;
ParentProcess *viewerP; // Used when the viewer launches engine
ViewerRemoteProcess *viewer; // Used when engine launches viewer
stringVector viewerArgs; // "
bool reverseLaunch;
// The destination machine's type representation.
TypeRepresentation destinationFormat;
......
......@@ -50,11 +50,12 @@
// this, we should remove this include directive
#include <InvalidVariableException.h>
#include <DebugStream.h>
#include <ExpressionList.h>
#include <ParentProcess.h>
#include <RemoteProcess.h>
#include <SocketConnection.h>
#include <StatusAttributes.h>
#include <ExpressionList.h>
#include <DebugStream.h>
#include <TimingsManager.h>
#include <snprintf.h>
......@@ -88,10 +89,15 @@
// Brad Whitlock, Thu Jan 25 13:53:15 PST 2007
// Added commandFromSim.
//
// Brad Whitlock, Thu Apr 9 15:04:14 PDT 2009
// Add engineP.
//
// ****************************************************************************
EngineProxy::EngineProxy() : RemoteProxyBase("-engine")
{
engineP = NULL;
// Indicate that we want 2 write sockets from the engine.
nWrite = 2;
......@@ -142,6 +148,9 @@ EngineProxy::EngineProxy() : RemoteProxyBase("-engine")
// Brad Whitlock, Thu Jan 25 13:53:36 PST 2007
// Delete commandFromSim.
//
// Brad Whitlock, Thu Apr 9 15:03:57 PDT 2009
// Delete engineP.
//
// ****************************************************************************
EngineProxy::~EngineProxy()
......@@ -150,6 +159,60 @@ EngineProxy::~EngineProxy()
delete metaData;
delete silAtts;
delete commandFromSim;
delete engineP;
}
// ****************************************************************************
// Method: EngineProxy::Create
//
// Purpose:
// This method is used to connect to an existing compute engine.
//
// Arguments:
// args : The arguments that we need to connect back to the engine.
//
// Returns:
//
// Note:
//
// Programmer: Brad Whitlock
// Creation: Thu Apr 9 15:07:34 PDT 2009
//
// Modifications:
//
// ****************************************************************************
void
EngineProxy::Connect(const stringVector &args)
{
char **argv = new char*[args.size()+1];
for(size_t i = 0; i <= args.size(); ++i)
{
if(i < args.size())
argv[i] = (char*)args[i].c_str();
else
argv[i] = NULL;
}
int argc = args.size();
engineP = new ParentProcess;
engineP->Connect(1, 2, &argc, &argv, true);
delete [] argv;
// Use engineP's connections for xfer.
xfer.SetInputConnection(engineP->GetWriteConnection());
xfer.SetOutputConnection(engineP->GetReadConnection());
//
// Set up the RPCs
//
SetupAllRPCs();
//
// List the objects that were hooked up.
//
xfer.ListObjects();
}
// ****************************************************************************
......@@ -339,7 +402,9 @@ EngineProxy::GetComponentName() const
// Creation: Fri Mar 12 11:04:57 PDT 2004
//
// Modifications:
//
// Brad Whitlock, Thu Apr 9 16:15:50 PDT 2009
// I added reverse launch support.
//
// ****************************************************************************
void
......@@ -358,8 +423,16 @@ EngineProxy::SendKeepAlive()
//
#define KEEPALIVE_SIZE 10
unsigned char buf[KEEPALIVE_SIZE];
if (component->GetWriteConnection(1)->DirectRead(buf, KEEPALIVE_SIZE) < 0)
debug1 << "Error reading keep alive data from engine!!!!\n";
if(engineP != NULL)
{
if (engineP->GetReadConnection(1)->DirectRead(buf, KEEPALIVE_SIZE) < 0)
debug1 << "Error reading keep alive data from engine!!!!\n";
}
else
{
if (component->GetWriteConnection(1)->DirectRead(buf, KEEPALIVE_SIZE) < 0)
debug1 << "Error reading keep alive data from engine!!!!\n";
}
}
// ****************************************************************************
......@@ -694,6 +767,9 @@ EngineProxy::SetWinAnnotAtts(const WindowAttributes *winAtts,
// Kathleen Bonnell, Thu Jun 12 10:53:29 PDT 2003
// Added timing code for delay before read, and read.
//
// Brad Whitlock, Thu Apr 9 16:17:36 PDT 2009
// I added reverse launch support.
//
// ****************************************************************************
avtDataObjectReader_p
......@@ -752,12 +828,23 @@ EngineProxy::Execute(bool respondWithNull, void (*waitCB)(void *), void *cbData)
long size = executeRPC.GetReplyLen();
char *buf = new char[size];
component->GetWriteConnection(1)->NeedsRead(true);
if(engineP != NULL)
engineP->GetReadConnection(1)->NeedsRead(true);
else
component->GetWriteConnection(1)->NeedsRead(true);
visitTimer->StopTimer(readDelay, "Delay between read notification and actual read");
int readData = visitTimer->StartTimer();
if (component->GetWriteConnection(1)->DirectRead((unsigned char *)buf, size) < 0)
debug1 << "Error reading VTK data!!!!\n";
if(engineP != NULL)
{
if (engineP->GetReadConnection(1)->DirectRead((unsigned char *)buf, size) < 0)
debug1 << "Error reading VTK data!!!!\n";
}
else
{
if (component->GetWriteConnection(1)->DirectRead((unsigned char *)buf, size) < 0)
debug1 << "Error reading VTK data!!!!\n";
}
char msg[128];
SNPRINTF(msg, 128, "Reading %ld bytes from socket", size);
......@@ -915,6 +1002,10 @@ EngineProxy::DefineVirtualDatabase(const std::string &fileFormat,
//
// Mark C. Miller, Mon Apr 14 15:41:21 PDT 2008
// Removed conditionally removed code block conditioned on 'MCM_FIX'
//
// Brad Whitlock, Thu Apr 9 16:17:55 PDT 2009
// I added reverse launch support.
//
// ****************************************************************************
avtDataObjectReader_p
......@@ -973,8 +1064,16 @@ EngineProxy::Render(bool sendZBuffer, const intVector& networkIDs,
long size = renderRPC.GetReplyLen();
char *buf = new char[size];
if (component->GetWriteConnection(1)->DirectRead((unsigned char *)buf, size) < 0)
debug1 << "Error reading VTK data!!!!\n";
if(engineP != NULL)
{
if (engineP->GetReadConnection(1)->DirectRead((unsigned char *)buf, size) < 0)
debug1 << "Error reading VTK data!!!!\n";
}
else
{
if (component->GetWriteConnection(1)->DirectRead((unsigned char *)buf, size) < 0)
debug1 << "Error reading VTK data!!!!\n";
}
// The data object reader will clean up the memory with buf.
avtDataObjectReader_p avtreader = new avtDataObjectReader;
......
......@@ -83,6 +83,7 @@
class StatusAttributes;
class ConstructDDFAttributes;
class ExportDBAttributes;
class ParentProcess;
// ****************************************************************************
// Class: EngineProxy
......@@ -308,6 +309,9 @@ class ExportDBAttributes;
// Hank Childs, Wed Jan 28 15:57:02 PST 2009
// Add support for named selections.
//
// Brad Whitlock, Thu Apr 9 15:02:51 PDT 2009
// I added reverse launch support.
//
// ****************************************************************************
class ENGINE_PROXY_API EngineProxy : public RemoteProxyBase
......@@ -316,6 +320,9 @@ public:
EngineProxy();
virtual ~EngineProxy();
// This version of Create is specifically for reverse launch.
void Connect(const stringVector &args);
virtual void SendKeepAlive();
virtual bool Parallel() const { return numProcs > 1; };
......@@ -431,6 +438,8 @@ protected:
void ClearStatus();
void Warning(const char *message);
private:
ParentProcess *engineP;
ReadRPC readRPC;
ApplyOperatorRPC applyOperatorRPC;
MakePlotRPC makePlotRPC;
......
......@@ -264,6 +264,7 @@ ViewerEngineManager::EngineExists(const EngineKey &ek) const
// args the arguments to pass to the engine
// skipChooser do we not want to ask the user which profile to use
// numRestarts the number of restart attempts to use when engines fail
// reverseLaunch Whether the engine is being reverse launched (engine launched viewer)
//
// Programmer: Eric Brugger
// Creation: September 23, 2000
......@@ -403,9 +404,7 @@ ViewerEngineManager::EngineExists(const EngineKey &ek) const
bool
ViewerEngineManager::CreateEngine(const EngineKey &ek,
const stringVector &args,
bool skipChooser,
int numRestarts_)
const stringVector &args, bool skipChooser, int numRestarts_, bool reverseLaunch)
{
if (numRestarts_ == -1)
{
......@@ -413,7 +412,7 @@ ViewerEngineManager::CreateEngine(const EngineKey &ek,
numRestarts = 2;
}
else
numRestarts = numRestarts_;
numRestarts = numRestarts_;
//
// Check if an engine already exists for the host.
......@@ -441,8 +440,11 @@ ViewerEngineManager::CreateEngine(const EngineKey &ek,
// Create a new engine proxy and add arguments from the profile to it.
//
newEngine.proxy = new EngineProxy;
bool addParallelArgs = !newEngine.profile.GetShareOneBatchJob();
newEngine.proxy->AddProfileArguments(newEngine.profile, addParallelArgs);
if(!reverseLaunch)
{
bool addParallelArgs = !newEngine.profile.GetShareOneBatchJob();
newEngine.proxy->AddProfileArguments(newEngine.profile, addParallelArgs);
}
//
// Add some arguments to the engine proxy before we try to
......@@ -492,10 +494,23 @@ ViewerEngineManager::CreateEngine(const EngineKey &ek,
inLaunch = true;
if (!ShouldShareBatchJob(ek.HostName()) &&
HostIsLocalHost(ek.HostName()))
newEngine.proxy->Create("localhost", chd, clientHostName,
manualSSHPort, sshPort, useTunneling);
else
{
if(reverseLaunch)
{
debug1 << "Connecting to an existing engine" << endl;
newEngine.proxy->Connect(args);
}
else
{
debug1 << "Launching a local engine" << endl;
newEngine.proxy->Create("localhost", chd, clientHostName,
manualSSHPort, sshPort, useTunneling);
}
}
else
{
debug1 << "Launching an engine with the launcher" << endl;
// Use VisIt's launcher to start the remote engine.
newEngine.proxy->Create(ek.HostName(), chd, clientHostName,
manualSSHPort, sshPort, useTunneling,
......
......@@ -285,6 +285,9 @@ class FileOpenOptions;
// Hank Childs, Wed Jan 28 15:03:08 PST 2009
// Add support for named selections.
//
// Brad Whitlock, Thu Apr 9 15:18:44 PDT 2009
// I added another argument to CreateEngine that permits reverse launches.
//
// ****************************************************************************
class VIEWER_API ViewerEngineManager : public ViewerServerManager,
......@@ -304,7 +307,8 @@ class VIEWER_API ViewerEngineManager : public ViewerServerManager,
bool CreateEngine(const EngineKey &ek,
const std::vector<std::string> &arguments,
bool skipChooser=false,
int numRestarts=-1);
int numRestarts=-1,
bool reverseLaunch = false);
bool ConnectSim(const EngineKey &ek,
const std::vector<std::string> &arguments,
......
......@@ -226,9 +226,13 @@ using std::string;
// Brad Whitlock, Thu Aug 14 09:57:59 PDT 2008
// Removed mainApp, Added call to CreateState.
//
// Brad Whitlock, Thu Apr 9 15:58:47 PDT 2009
// I initialized openDatabaseOnStartup, openScriptOnStartup.
//
// ****************************************************************************
ViewerSubject::ViewerSubject() : ViewerBase(0),
launchEngineAtStartup(), openDatabaseOnStartup(), openScriptOnStartup(),
interpretCommands(), xfer(), clients(),
borders(), shift(), preshift(), geometry(),
engineParallelArguments(), unknownArguments(), clientArguments(),
......@@ -263,11 +267,6 @@ ViewerSubject::ViewerSubject() : ViewerBase(0),
//
launchingComponent = false;
//
// Will be set by the -launchengine flag.
//
launchEngineAtStartup = "";
//
// Set by BlockSocketSignals method.
//
......@@ -935,6 +934,9 @@ ViewerSubject::InformClientOfPlugins() const
// Added code to set up ViewerMethods so it writes into a buffered viewer
// state that gets copied into the central xfer's input buffer.
//
// Brad Whitlock, Thu Apr 9 15:59:56 PDT 2009
// I added code to open a file on startup.
//
// ****************************************************************************
void
......@@ -1028,6 +1030,12 @@ ViewerSubject::HeavyInitialization()
// Discover the client's information.
QTimer::singleShot(100, this, SLOT(DiscoverClientInformation()));
// Open a database on startup.
QTimer::singleShot(100, this, SLOT(OpenDatabaseOnStartup()));
// Open a script on startup.
QTimer::singleShot(100, this, SLOT(OpenScriptOnStartup()));
heavyInitializationDone = true;
visitTimer->StopTimer(timeid, "Heavy initialization.");
}
......@@ -1652,6 +1660,9 @@ ViewerSubject::AddInitialWindows()
// connecting to a running simulation at startup (right now), so we
// can safely call CreateEngine instead of ConnectSim.
//
// Brad Whitlock, Thu Apr 9 14:39:12 PDT 2009
// I added support for reverse launching.
//
// ****************************************************************************
void
......@@ -1662,10 +1673,94 @@ ViewerSubject::LaunchEngineOnStartup()
//
if (launchEngineAtStartup != "")
{
stringVector noArgs;
ViewerEngineManager::Instance()->
CreateEngine(EngineKey(launchEngineAtStartup,""),
engineParallelArguments, true, numEngineRestarts);
if(launchEngineAtStartup.substr(0,6) == "-host=")
{
stringVector tokens = SplitValues(launchEngineAtStartup, ',');
stringVector args;
args.push_back("visit");
for(size_t i = 0; i < tokens.size(); ++i)
{
stringVector comps = SplitValues(tokens[i], '=');
if(comps.size() == 1)
args.push_back(comps[0]);
else if(comps.size() == 2)
{
args.push_back(comps[0]);
args.push_back(comps[1]);
}
}
ViewerEngineManager::Instance()->CreateEngine(
EngineKey("localhost",""), // The name of the engine (host)
args, // The engine arguments
true, // Whether to skip the engine chooser
numEngineRestarts, // Number of allowed restarts
true); // Whether we're reverse launching
ViewerWindowManager::Instance()->ShowAllWindows();
}
else
{
ViewerEngineManager::Instance()->CreateEngine(
EngineKey(launchEngineAtStartup,""), // The name of the engine (host)
engineParallelArguments, // The engine arguments
true, // Whether to skip the engine chooser
numEngineRestarts, // Number of allowed restarts
false); // Whether we're reverse launching
}
}
}
// ****************************************************************************
// Method: ViewerSubject::OpenDatabaseOnStartup
//
// Purpose:
// This method opens a file on startup if there is a file to open.
//
// Programmer: Brad Whitlock
// Creation: Thu Apr 9 16:05:43 PDT 2009
//
// Modifications:
//
// ****************************************************************************
void
ViewerSubject::OpenDatabaseOnStartup()
{
if(openDatabaseOnStartup != "")
{
OpenDatabaseHelper(openDatabaseOnStartup, // DB name
0, // timeState,
true, // addDefaultPlots
true, // updateWindowInfo,
""); // forcedFileType
ViewerWindowManager::Instance()->UpdateActions();
}
}
// ****************************************************************************
// Method: ViewerSubject::OpenScriptOnStartup
//
// Purpose:
// This method opens a script on startup if there is a script to open.
//
// Programmer: Brad Whitlock
// Creation: Thu Apr 9 16:05:43 PDT 2009
//
// Modifications:
//
// ****************************************************************************
void
ViewerSubject::OpenScriptOnStartup()
{
if(openScriptOnStartup != "")
{
std::string cmd("Source('");
cmd += openScriptOnStartup;
cmd += "')";
InterpretCommands(cmd);
}
}
......@@ -2325,6 +2420,9 @@ ViewerSubject::ReadConfigFiles(int argc, char **argv)
// convenience. This will even override whatever the setting is in
// a selected host profile.
//
// Brad Whitlock, Thu Apr 9 14:45:03 PDT 2009
// I added -connectengine support and -o and -s support.
//
// ****************************************************************************
void
......@@ -2590,6 +2688,38 @@ debug1 << "Processing option " << i << " " << argv[i] << endl;
launchEngineAtStartup = argv[i+1];
++i;
}
else if (strcmp(argv[i], "-connectengine") == 0)
{
if(i + 1 >= argc)
{
cerr << "The -connectengine option must be followed by an "
"argument containing the engine connection parameters. "
"That argument is of the form: -host=val,-key=val,-port=val" << endl;
continue;
}
launchEngineAtStartup = argv[i+1];
++i;
}
else if (strcmp(argv[i], "-o") == 0)
{
if(i + 1 >= argc)
{
cerr << "The -o option must be followed by a filename." << endl;
continue;
}
openDatabaseOnStartup = argv[i+1];
++i;
}
else if (strcmp(argv[i], "-s") == 0)
{
if(i + 1 >= argc)
{
cerr << "The -s option must be followed by a script filename." << endl;
continue;
}
openScriptOnStartup = argv[i+1];
++i;
}
else if (strcmp(argv[i], "-key") == 0)
{
if(i + 1 >= argc)
......
......@@ -719,6 +719,8 @@ private slots:
void CopyAnnotationsToWindow(int from, int to);
void CopyPlotsToWindow(int from, int to);
void OpenDatabaseOnStartup();
void OpenScriptOnStartup();
private:
typedef std::vector<ViewerClientConnection *> ViewerClientConnectionVector;
static void BroadcastToAllClients(void *, Subject *);
......@@ -731,6 +733,8 @@ private:
bool heavyInitializationDone;
bool interruptionEnabled;
std::string launchEngineAtStartup;
std::string openDatabaseOnStartup;
std::string openScriptOnStartup;
bool blockSocketSignals;
bool processingFromParent;
int animationStopOpcode;
......
......@@ -116,6 +116,10 @@ Viewer_LogQtMessages(QtMsgType type, const char *msg)
// Prevent Qt from getting the -geometry flag since it messes up the
// viswin's initial size on X11 with Qt 4.
//
// Brad Whitlock, Thu Apr 9 14:19:51 PDT 2009
// Skip connecting to the client if we're doing a -connectengine, which
// means the engine and not the client is launching the viewer.
//
// ****************************************************************************
int
......@@ -137,9 +141,14 @@ main(int argc, char *argv[])
VisItViewer viewer;
//
// Connect back to the client.
// Connect back to the client if we're not doing a reverse launch from
// the compute engine.
//
viewer.Connect(&argc, &argv);
bool reverseLaunch = false;
for(int i = 1; i < argc && !reverseLaunch; ++i)
reverseLaunch |= (strcmp(argv[i], "-connectengine") == 0);
if(!reverseLaunch)
viewer.Connect(&argc, &argv);
//
// Process the command line arguments first since some may be removed
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment