[RavenclawDev 287] [928] Pythia: 1) Extended Pythia to support remote dynamic configuration.
tk@edam.speech.cs.cmu.edu
tk at edam.speech.cs.cmu.edu
Tue Jul 3 23:00:26 EDT 2007
An HTML attachment was scrubbed...
URL: http://mailman.srv.cs.cmu.edu/pipermail/ravenclaw-developers/attachments/20070703/00da9b6e/attachment-0001.html
-------------- next part --------------
Property changes on: Pythia/PythiaDynamicClient
___________________________________________________________________
Name: svn:ignore
+ *.ncb
*.suo
*.user
Added: Pythia/PythiaDynamicClient/Debug/PythiaDynamicClient.lib
===================================================================
(Binary files differ)
Property changes on: Pythia/PythiaDynamicClient/Debug/PythiaDynamicClient.lib
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: Pythia/PythiaDynamicClient/PythiaDynamicClient.cpp
===================================================================
--- Pythia/PythiaDynamicClient/PythiaDynamicClient.cpp (rev 0)
+++ Pythia/PythiaDynamicClient/PythiaDynamicClient.cpp 2007-07-04 03:00:24 UTC (rev 928)
@@ -0,0 +1,70 @@
+#ifdef WIN32
+#include <winsock2.h>
+#else
+#error fixme
+#endif
+
+#include <iostream>
+#include <sstream>
+
+#include "PythiaDynamicClient.h"
+
+using namespace std;
+
+namespace Pythia {
+
+ const short Message::_port = 11044;
+
+ Message::Message(const string& cmd, const string title, const string dir) : _cmd(cmd), _title(title), _dir(dir) {
+#ifdef WIN32
+ WSADATA wsaData;
+ if(WSAStartup(MAKEWORD(2,0),&wsaData)!=0) {
+ cerr << "Socket initialization error" << endl;
+ }
+#endif
+ }
+
+ void Message::send(const string& host) const {
+ SOCKET sockfd;
+ if((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {
+ cerr << "Invalid socket " << GetLastError() << endl;
+ return;
+ }
+
+ SOCKADDR_IN servaddr;
+ {
+ memset(&servaddr, 0, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_port = htons(_port);
+ struct hostent* hp;
+ if((hp = gethostbyname(host.c_str())) == NULL) {
+ cerr << "Unable to get hostent for " << host << endl;
+ return;
+ }
+ memcpy(&servaddr.sin_addr, (hp->h_addr_list)[0], sizeof(struct in_addr));
+ }
+
+ int lConnect;
+ if((lConnect = connect(sockfd,(SOCKADDR *)&servaddr,sizeof(SOCKADDR_IN))) != 0) {
+ cerr << "Connect Error" << endl;
+ return;
+ }
+
+ string msg = formMessage();
+ if(::send(sockfd, msg.c_str(), (int)msg.length() ,0) < (int)msg.length()) {
+ cerr << "Send Error" << endl;
+ }
+
+ closesocket(sockfd);
+ }
+
+ string Message::formMessage() const {
+ ostringstream ret;
+ ret << "PROCESS: " << _cmd << endl;
+ ret << "PROCESS_MONITOR_ARGS: --start" << endl;
+ if(!_dir.empty()) ret << "PROCESS_WORKDIR: " << _dir << endl;
+ if(!_title.empty()) ret << "PROCESS_TITLE: " << _title << endl;
+ return ret.str();
+ }
+
+}
\ No newline at end of file
Added: Pythia/PythiaDynamicClient/PythiaDynamicClient.h
===================================================================
--- Pythia/PythiaDynamicClient/PythiaDynamicClient.h (rev 0)
+++ Pythia/PythiaDynamicClient/PythiaDynamicClient.h 2007-07-04 03:00:24 UTC (rev 928)
@@ -0,0 +1,22 @@
+#ifndef PYTHIA_DYNAMIC_CLIENT_H
+#define PYTHIA_DYNAMIC_CLIENT_H
+
+#include <string>
+using namespace std;
+
+namespace Pythia {
+
+ class Message {
+ private:
+ string _title, _dir, _cmd;
+ static const short _port;
+ public:
+ Message(const string& cmd, const string title=string(), const string dir=string());
+ void send(const string& host) const;
+ protected:
+ string formMessage() const;
+ };
+
+}
+
+#endif
\ No newline at end of file
Added: Pythia/PythiaDynamicClient/PythiaDynamicClient.sln
===================================================================
--- Pythia/PythiaDynamicClient/PythiaDynamicClient.sln (rev 0)
+++ Pythia/PythiaDynamicClient/PythiaDynamicClient.sln 2007-07-04 03:00:24 UTC (rev 928)
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PythiaDynamicClient", "PythiaDynamicClient.vcproj", "{BC3C2AF0-EF36-4587-B384-E154B6EDCC33}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {BC3C2AF0-EF36-4587-B384-E154B6EDCC33}.Debug|Win32.ActiveCfg = Debug|Win32
+ {BC3C2AF0-EF36-4587-B384-E154B6EDCC33}.Debug|Win32.Build.0 = Debug|Win32
+ {BC3C2AF0-EF36-4587-B384-E154B6EDCC33}.Release|Win32.ActiveCfg = Release|Win32
+ {BC3C2AF0-EF36-4587-B384-E154B6EDCC33}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
Added: Pythia/PythiaDynamicClient/PythiaDynamicClient.vcproj
===================================================================
--- Pythia/PythiaDynamicClient/PythiaDynamicClient.vcproj (rev 0)
+++ Pythia/PythiaDynamicClient/PythiaDynamicClient.vcproj 2007-07-04 03:00:24 UTC (rev 928)
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="PythiaDynamicClient"
+ ProjectGUID="{BC3C2AF0-EF36-4587-B384-E154B6EDCC33}"
+ RootNamespace="PythiaDynamicClient"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ WholeProgramOptimization="false"
+ PreprocessorDefinitions="WIN32"
+ RuntimeLibrary="2"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\PythiaDynamicClient.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\PythiaDynamicClient.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
Added: Pythia/PythiaDynamicClient/Release/PythiaDynamicClient.lib
===================================================================
(Binary files differ)
Property changes on: Pythia/PythiaDynamicClient/Release/PythiaDynamicClient.lib
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: Pythia/dist/library.zip
===================================================================
(Binary files differ)
Modified: Pythia/dist/process_monitor.exe
===================================================================
(Binary files differ)
Modified: Pythia/src/basic_process_monitor.py
===================================================================
--- Pythia/src/basic_process_monitor.py 2007-07-02 23:10:19 UTC (rev 927)
+++ Pythia/src/basic_process_monitor.py 2007-07-04 03:00:24 UTC (rev 928)
@@ -680,12 +680,32 @@
return (config_entry[-1] == self.container_set_class) and \
(config_entry[-2] == 1)
+ def DynamicCallback(self, directives):
+ cur_set = self.cur_set
+ cur_container = self.cur_container
+ for key, val in directives:
+ cur_set, cur_container = self._ConfigureOption(cur_set, cur_container, key, val, 0, self._AssembleConfiguration())
+ cur_container.ConfigDone()
+ for p in cur_set.processes:
+ if (not (p == None)) and p.title == cur_container.title and p != cur_container:
+ cur_set.processes[-1:] = []
+ cur_container = p
+ break
+ if not cur_set.UnmetRequirements():
+ cur_set.meets_requirements = 1
+ else:
+ cur_set.meets_requirements = 0
+ print "unmet requirements"
+ return cur_container
+
def _Configure(self, optlist, from_cmdline, config_dict):
# So now we work our way through the optlist.
cur_set = None
cur_container = None
for key, val in optlist:
cur_set, cur_container = self._ConfigureOption(cur_set, cur_container, key, val, from_cmdline, config_dict)
+ self.cur_set = cur_set
+ self.cur_container = cur_container
def _ConfigureOption(self, cur_set, cur_container,
key, val, from_cmdline, config_dict):
@@ -741,7 +761,7 @@
else:
kmethod()
return cur_set, cur_container
-
+
def ChooseConfig(self):
p_set = None
if self.num_conforming_process_sets == 0:
Modified: Pythia/src/process_monitor.py
===================================================================
--- Pythia/src/process_monitor.py 2007-07-02 23:10:19 UTC (rev 927)
+++ Pythia/src/process_monitor.py 2007-07-04 03:00:24 UTC (rev 928)
@@ -29,7 +29,7 @@
-c "bin/hub -pgm_file addmultiply.pgm"
"""
-import os, sys, socket, string, signal, select, math, time
+import os, sys, socket, string, signal, select, math, time, Queue
import Tkinter
from Tkinter import *
@@ -319,7 +319,7 @@
Frame.__init__(self, master)
self['borderwidth'] = 2
# Default title.
- self.master.title("Process monitor")
+ self.master.title("Pythia process monitor")
self.pack(fill = 'both', expand = 1)
self.top = Frame(self)
self.top.pack(side = 'top', fill = 'x', anchor = 'w')
@@ -387,12 +387,26 @@
self.process_env = process_env
# For temporary files.
self.process_env.Initialize()
- self.master.iconbitmap(default=process_env.icon)
+ try: self.master.iconbitmap(default=process_env.icon)
+ except: pass
self.process_set = None
self.UseProcessSet(process_set)
+ self.calls = Queue.Queue(10)
+ def QDynamicCallback(self, directives):
+ self.calls.put(directives)
+
+ def handle_calls(self):
+ while not self.calls.empty():
+ directives = self.calls.get()
+ self.DynamicCallback(directives)
+
+ def DynamicCallback(self, directives):
+ proc = self.process_env.DynamicCallback(directives)
+ if not proc == None:
+ self.DynamicProcess(proc)
+
def UseProcessSet(self, new_set):
-
# First, shut down and delete all windows, if
# appropriate.
if self.process_set:
@@ -454,6 +468,54 @@
else:
self.UseColumnConfig(self.process_env.ncols)
+ def DynamicProcess(self, proc):
+ # If this process is already attached then we may just want to start it
+ try:
+ if not proc.tk == None:
+ if proc.start and proc.Dead():
+ proc.window_host.Restart()
+ return
+ except:
+ pass
+
+ # Build a frame which has the lower pane as a hidden
+ # component.
+ # Set up the reference line.
+ proc.AddTk(self.tk)
+ self.AttachProcess(proc)
+ if proc.open:
+ proc.reference_entry.Enlarge()
+ if proc.start:
+ proc.window_host.Restart()
+ if proc.keepalive:
+ proc.window_host.KeepAlive()
+ # Now, build the button.
+ b = Button(self.button_row,
+ text = proc.title,
+ relief = 'raised',
+ font = HEADERFONT)
+ proc.compressed_button = b
+ b.configure(command = lambda p = proc, s = self:
+ s.MakeButtonActive(p))
+
+ # Now, we need to regenerate things.
+ if self.compressed:
+ # Regenerate the compressed list.
+ self.UnuseCompressedConfig()
+ self.separator_list.append(Frame(self.pane_frame,
+ relief = 'sunken',
+ height = 2,
+ borderwidth = 1))
+ self.UseCompressedConfig(self.numcols, force = 1)
+ else:
+ # Regenerate the uncompressed structure.
+ self.UnuseColumnConfig()
+ self.separator_list.append(Frame(self.pane_frame,
+ relief = 'sunken',
+ height = 2,
+ borderwidth = 1))
+ self.UseColumnConfig(self.numcols, force = 1)
+
def AttachProcess(self, p):
ref = ReferenceEntry(self.pane_frame, self, p)
p.SetReferenceEntry(ref)
@@ -677,8 +739,13 @@
p.Poll()
self.timer = self.tk.createtimerhandler(500, self.Poll)
+ def handle_calls_callback(self):
+ self.handle_calls()
+ self.after(1000, self.handle_calls_callback)
+
def Run(self):
# self.timer = self.tk.createtimerhandler(500, self.Poll)
+ self.handle_calls_callback()
self.mainloop()
# We adopt a more complex model, where all the info about
@@ -755,6 +822,8 @@
from basic_process_monitor import ProcessContainer, \
ProcessContainerSet, ProcessEnvironment, ConfigurationError
+from spawn_listener import SpawnListener
+
class TkProcessContainer(ProcessContainer):
config_table = ProcessContainer.config_table + \
[(None, "--input_line", 0, "LineInputMode", 0),
@@ -1178,11 +1247,14 @@
if hasattr(signal, "SIGQUIT"):
# Doesn't exist on Windows.
signal.signal(signal.SIGQUIT, lambda n, stack, s = f: s.force_quit())
+ listener = SpawnListener(f.QDynamicCallback)
try:
+ listener.start()
f.Run()
except "foo":
print "Encountered an unrecoverable error of type %s with argument %s. Exiting." % (`sys.exc_type`, `sys.exc_value`)
sys.stdout.flush()
f.quit()
+
main()
Added: Pythia/src/spawn_listener.py
===================================================================
--- Pythia/src/spawn_listener.py (rev 0)
+++ Pythia/src/spawn_listener.py 2007-07-04 03:00:24 UTC (rev 928)
@@ -0,0 +1,43 @@
+# Thomas Harris <tkharris at cs.cmu.edu>
+# December 2006
+#
+# This process listens for spawn requests on a known tcp port
+
+import socket, threading, string
+
+_port = 11044
+
+class SpawnListener(threading.Thread):
+ def __init__(self, dynamic_callback):
+ threading.Thread.__init__(self)
+ self.setDaemon(1)
+ self.serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.serversocket.bind(('', _port))
+ self.serversocket.listen(5)
+ self.dynamic_callback = dynamic_callback
+
+ def run(self):
+ while 1:
+ (clientsocket, address) = self.serversocket.accept()
+ msg = ''
+ while 1:
+ chunk = clientsocket.recv(1024)
+ if chunk == '':
+ break
+ msg = msg + chunk
+ self._processMsg(msg)
+
+ def _processMsg(self, msg):
+ lines = msg.splitlines()
+ directives = []
+ for line in lines:
+ l = string.strip(line)
+ if l and l[0] != '#':
+ d = string.split(l, None, 1)
+ if len(d) == 1:
+ directives.append((d[0], ""))
+ else:
+ directives.append((d[0], d[1]))
+ self.dynamic_callback(directives)
+
+
More information about the Ravenclaw-developers
mailing list