Free cookie consent management tool by TermsFeed Policy Generator

Changeset 440


Ignore:
Timestamp:
08/04/08 16:47:45 (16 years ago)
Author:
gkronber
Message:
  • split the GridForm class into two classes GridForm and GridClient
  • added class EngineRunner to act as the bridge between the AppDomain where engines are executed and the main AppDomain of the client.
  • GridClient creates a new AppDomain for each engine and unloads it again when the engine is finished.

(ticket #230)

Location:
trunk/sources/HeuristicLab.Grid
Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Grid/ClientForm.cs

    r439 r440  
    3838namespace HeuristicLab.Grid {
    3939  public partial class ClientForm : Form {
    40     private ChannelFactory<IEngineStore> factory;
    41     private System.Timers.Timer fetchOperationTimer;
    42     private IEngineStore engineStore;
    43     private Guid currentGuid;
    44     private ProcessingEngine currentEngine;
    45     private object connectionLock = new object();
    46     private bool stopped;
    47     private const int CONNECTION_RETRY_TIMEOUT_SEC = 10;
    48     private const int MAX_RETRIES = 10;
     40    private GridClient client;
     41    public ClientForm() {
     42      Trace.Listeners.Clear();
     43      Trace.Listeners.Add(new EventLogTraceListener("HeuristicLab.Grid"));
    4944
    50     public ClientForm() {
    5145      InitializeComponent();
    52       fetchOperationTimer = new System.Timers.Timer();
    53       fetchOperationTimer.Interval = 200;
    54       fetchOperationTimer.Elapsed += new System.Timers.ElapsedEventHandler(fetchOperationTimer_Elapsed);
    55       statusTextBox.Text = "Stopped";
    56       stopped = true;
    57       currentGuid = Guid.Empty;
     46
     47      client = new GridClient();
     48      UpdateControl();
    5849    }
    5950
    6051    private void startButton_Click(object sender, EventArgs e) {
    61       try {
    62         Trace.Listeners.Clear();
    63         Trace.Listeners.Add(new EventLogTraceListener("HeuristicLab.Grid"));
     52      client.Start(addressTextBox.Text);
     53      UpdateControl();
     54    }
    6455
    65         ResetConnection();
    66         fetchOperationTimer.Start();
     56    private void stopButton_Click(object sender, EventArgs e) {
     57      client.Stop();
     58      UpdateControl();
     59    }
     60
     61    private void UpdateControl() {
     62      if(client.Waiting) {
    6763        startButton.Enabled = false;
    6864        stopButton.Enabled = true;
    6965        statusTextBox.Text = "Waiting for engine";
    70         stopped = false;
    71 
    72       } catch(CommunicationException ex) {
    73         MessageBox.Show("Exception while connecting to the server: " + ex.Message);
     66      } else if(client.Executing) {
     67        startButton.Enabled = false;
     68        stopButton.Enabled = true;
     69        statusTextBox.Text = "Executing engine";
     70      } else if(client.Stopped) {
    7471        startButton.Enabled = true;
    7572        stopButton.Enabled = false;
    76         fetchOperationTimer.Stop();
     73        statusTextBox.Text = "Stopped";
    7774      }
     75      statusStrip.Text = client.StatusMessage;
    7876    }
    7977
    80     private void ResetConnection() {
    81       Trace.TraceInformation("Reset connection in GridClient");
    82       NetTcpBinding binding = new NetTcpBinding();
    83       binding.MaxReceivedMessageSize = 100000000; // 100Mbytes
    84       binding.ReaderQuotas.MaxStringContentLength = 100000000; // also 100M chars
    85       binding.ReaderQuotas.MaxArrayLength = 100000000; // also 100M elements;
    86       binding.Security.Mode = SecurityMode.None;
    87       factory = new ChannelFactory<IEngineStore>(binding);
    88       engineStore = factory.CreateChannel(new EndpointAddress(addressTextBox.Text));
    89     }
    90 
    91     private void stopButton_Click(object sender, EventArgs e) {
    92       stopped = true;
    93       fetchOperationTimer.Stop();
    94       if(currentEngine != null)
    95         currentEngine.Abort();
    96       lock(connectionLock) {
    97         if(factory.State == CommunicationState.Opened || factory.State == CommunicationState.Opening) {
    98           IAsyncResult closeResult = factory.BeginClose(null, null);
    99           factory.EndClose(closeResult);
    100         }
    101       }
    102       statusTextBox.Text = "Stopped";
    103       stopButton.Enabled = false;
    104       startButton.Enabled = true;
    105     }
    106 
    107     private void fetchOperationTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
    108       byte[] engineXml = null;
    109       // first stop the timer!
    110       fetchOperationTimer.Stop();
    111       bool gotEngine = false;
    112       lock(connectionLock) {
    113         if(stopped) return;
    114         try {
    115           gotEngine = engineStore.TryTakeEngine(out currentGuid, out engineXml);
    116         } catch(TimeoutException) {
    117           Trace.TraceWarning("TimeoutException while trying to get an engine");
    118           currentEngine = null;
    119           currentGuid = Guid.Empty;
    120           // timeout -> just start the timer again
    121           fetchOperationTimer.Interval = 5000;
    122           fetchOperationTimer.Start();
    123         } catch(CommunicationException) {
    124           Trace.TraceWarning("CommunicationException while trying to get an engine");
    125           // connection problem -> reset connection and start the timer again
    126           ResetConnection();
    127           currentEngine = null;
    128           currentGuid = Guid.Empty;
    129           fetchOperationTimer.Interval = 5000;
    130           fetchOperationTimer.Start();
    131         }
    132       }
    133       // got engine from server and user didn't press stop -> execute the engine
    134       if(gotEngine && !stopped) {
    135         currentEngine = RestoreEngine(engineXml);
    136         if(InvokeRequired) { Invoke((MethodInvoker)delegate() { statusTextBox.Text = "Executing engine"; }); } else statusTextBox.Text = "Executing engine";
    137         currentEngine.Finished += new EventHandler(currentEngine_Finished); // register event-handler that sends result back to server and restarts timer
    138         currentEngine.Execute();
    139       } else {
    140         // ok we didn't get engine -> if the user didn't press stop this means that the server doesn't have engines for us
    141         // if the user pressed stop we must not start the timer
    142         if(!stopped) {
    143           if(InvokeRequired) { Invoke((MethodInvoker)delegate() { statusTextBox.Text = "Waiting for engine"; }); } else statusTextBox.Text = "Waiting for engine";
    144           // start the timer again
    145           fetchOperationTimer.Interval = 5000;
    146           fetchOperationTimer.Start();
    147         }
    148       }
    149     }
    150 
    151     void currentEngine_Finished(object sender, EventArgs e) {
    152       ProcessingEngine engine = (ProcessingEngine)sender;
    153 
    154       // if the engine was stopped because of an error (not suspended because of a breakpoint)
    155       // it's not necessary to return the whole engine
    156       // instead just return an empty engine that has the aborted flag set
    157       if(engine.Canceled && !engine.Suspended) {
    158         engine.Reset();
    159         engine.OperatorGraph.Clear();
    160         engine.Abort();
    161       }
    162 
    163       if(!engine.Canceled && !engine.Suspended) {
    164         engine.OperatorGraph.Clear();
    165         engine.GlobalScope.Clear();
    166       }
    167 
    168       byte[] resultXml = SaveEngine(engine);
    169       bool success = false;
    170       int retries = 0;
    171       do {
    172         lock(connectionLock) {
    173           if(!stopped) {
    174             try {
    175               engineStore.StoreResult(currentGuid, resultXml);
    176               success = true;
    177             } catch(TimeoutException) {
    178               Trace.TraceWarning("TimeoutException while trying to store the result of an engine");
    179               success = false;
    180               retries++;
    181               Thread.Sleep(TimeSpan.FromSeconds(CONNECTION_RETRY_TIMEOUT_SEC));
    182             } catch(CommunicationException) {
    183               Trace.TraceWarning("CommunicationException while trying to store the result of an engine");
    184               ResetConnection();
    185               success = false;
    186               retries++;
    187               Thread.Sleep(TimeSpan.FromSeconds(CONNECTION_RETRY_TIMEOUT_SEC));
    188             }
    189           }
    190         }
    191       } while(!stopped && !success && retries < MAX_RETRIES);
    192       // ok if we could store the result it's probable that the server can send us another engine use a small time-interval
    193       if(success)
    194         fetchOperationTimer.Interval = 100;
    195       else fetchOperationTimer.Interval = CONNECTION_RETRY_TIMEOUT_SEC; // if there were problems -> sleep for a longer time
    196       // clear state
    197       currentEngine = null;
    198       currentGuid = Guid.Empty;
    199       // start the timer
    200       fetchOperationTimer.Start();
    201     }
    202 
    203     private ProcessingEngine RestoreEngine(byte[] engine) {
    204       return (ProcessingEngine)PersistenceManager.RestoreFromGZip(engine);
    205     }
    206     private byte[] SaveEngine(IEngine engine) {
    207       return PersistenceManager.SaveToGZip(engine);
     78    private void timer_Tick(object sender, EventArgs e) {
     79      UpdateControl();
    20880    }
    20981  }
  • trunk/sources/HeuristicLab.Grid/ClientForm.designer.cs

    r314 r440  
    4545    /// </summary>
    4646    private void InitializeComponent() {
     47      this.components = new System.ComponentModel.Container();
    4748      this.label1 = new System.Windows.Forms.Label();
    4849      this.stopButton = new System.Windows.Forms.Button();
     
    5152      this.statusLabel = new System.Windows.Forms.Label();
    5253      this.statusTextBox = new System.Windows.Forms.TextBox();
     54      this.statusStrip = new System.Windows.Forms.StatusStrip();
     55      this.timer = new System.Windows.Forms.Timer(this.components);
    5356      this.SuspendLayout();
    5457      //
     
    6669      this.stopButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
    6770      this.stopButton.Enabled = false;
    68       this.stopButton.Location = new System.Drawing.Point(99, 59);
     71      this.stopButton.Location = new System.Drawing.Point(96, 61);
    6972      this.stopButton.Name = "stopButton";
    7073      this.stopButton.Size = new System.Drawing.Size(75, 23);
     
    7780      //
    7881      this.startButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
    79       this.startButton.Location = new System.Drawing.Point(15, 59);
     82      this.startButton.Location = new System.Drawing.Point(12, 61);
    8083      this.startButton.Name = "startButton";
    8184      this.startButton.Size = new System.Drawing.Size(75, 23);
     
    109112      this.statusTextBox.TabIndex = 9;
    110113      //
     114      // statusStrip
     115      //
     116      this.statusStrip.Location = new System.Drawing.Point(0, 87);
     117      this.statusStrip.Name = "statusStrip";
     118      this.statusStrip.Size = new System.Drawing.Size(330, 22);
     119      this.statusStrip.TabIndex = 10;
     120      this.statusStrip.Text = "statusStrip1";
     121      //
     122      // timer
     123      //
     124      this.timer.Enabled = true;
     125      this.timer.Interval = 1000;
     126      this.timer.Tick += new System.EventHandler(this.timer_Tick);
     127      //
    111128      // ClientForm
    112129      //
    113130      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
    114131      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    115       this.ClientSize = new System.Drawing.Size(330, 94);
     132      this.ClientSize = new System.Drawing.Size(330, 109);
     133      this.Controls.Add(this.statusStrip);
    116134      this.Controls.Add(this.statusTextBox);
    117135      this.Controls.Add(this.statusLabel);
     
    135153    private System.Windows.Forms.Label statusLabel;
    136154    private System.Windows.Forms.TextBox statusTextBox;
     155    private System.Windows.Forms.StatusStrip statusStrip;
     156    private System.Windows.Forms.Timer timer;
    137157  }
    138158}
  • trunk/sources/HeuristicLab.Grid/ClientForm.resx

    r2 r440  
    118118    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
    119119  </resheader>
     120  <metadata name="statusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     121    <value>17, 17</value>
     122  </metadata>
     123  <metadata name="timer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
     124    <value>121, 17</value>
     125  </metadata>
    120126</root>
  • trunk/sources/HeuristicLab.Grid/HeuristicLab.Grid.csproj

    r374 r440  
    6060      <DependentUpon>ClientForm.cs</DependentUpon>
    6161    </Compile>
     62    <Compile Include="EngineRunner.cs" />
    6263    <Compile Include="EngineStore.cs" />
     64    <Compile Include="GridClient.cs" />
    6365    <Compile Include="GridClientApplication.cs" />
    6466    <Compile Include="GridServer.cs" />
Note: See TracChangeset for help on using the changeset viewer.