Free cookie consent management tool by TermsFeed Policy Generator

source: branches/Collections/sources/HeuristicLab.Grid/ClientForm.cs @ 384

Last change on this file since 384 was 384, checked in by gkronber, 16 years ago

merged changesets r382 and r383 (fix references and compiler warnings) into the "collections" branch

File size: 7.6 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2008 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.ComponentModel;
25using System.Data;
26using System.Drawing;
27using System.Linq;
28using System.Text;
29using System.Windows.Forms;
30using System.ServiceModel;
31using HeuristicLab.Core;
32using System.Xml;
33using System.Threading;
34using System.IO;
35using System.IO.Compression;
36using System.Net;
37
38namespace HeuristicLab.Grid {
39  [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
40  public partial class ClientForm : Form {
41    private ChannelFactory<IEngineStore> factory;
42    private System.Timers.Timer fetchOperationTimer;
43    private IEngineStore engineStore;
44    private Guid currentGuid;
45    private ProcessingEngine currentEngine;
46    private object connectionLock = new object();
47    private bool stopped;
48    private const int CONNECTION_RETRY_TIMEOUT_SEC = 10;
49    private const int MAX_RETRIES = 10;
50
51    public ClientForm() {
52      InitializeComponent();
53      fetchOperationTimer = new System.Timers.Timer();
54      fetchOperationTimer.Interval = 200;
55      fetchOperationTimer.Elapsed += new System.Timers.ElapsedEventHandler(fetchOperationTimer_Elapsed);
56      statusTextBox.Text = "Stopped";
57      stopped = true;
58      currentGuid = Guid.Empty;
59    }
60
61    private void startButton_Click(object sender, EventArgs e) {
62      try {
63        ResetConnection();
64        fetchOperationTimer.Start();
65        startButton.Enabled = false;
66        stopButton.Enabled = true;
67        statusTextBox.Text = "Waiting for engine";
68        stopped = false;
69
70      } catch(CommunicationException ex) {
71        MessageBox.Show("Exception while connecting to the server: " + ex.Message);
72        startButton.Enabled = true;
73        stopButton.Enabled = false;
74        fetchOperationTimer.Stop();
75      }
76    }
77
78    private void ResetConnection() {
79      NetTcpBinding binding = new NetTcpBinding();
80      binding.MaxReceivedMessageSize = 100000000; // 100Mbytes
81      binding.ReaderQuotas.MaxStringContentLength = 100000000; // also 100M chars
82      binding.ReaderQuotas.MaxArrayLength = 100000000; // also 100M elements;
83      binding.Security.Mode = SecurityMode.None;
84      factory = new ChannelFactory<IEngineStore>(binding);
85      engineStore = factory.CreateChannel(new EndpointAddress(addressTextBox.Text));
86    }
87
88    private void stopButton_Click(object sender, EventArgs e) {
89      stopped = true;
90      fetchOperationTimer.Stop();
91      if(currentEngine != null)
92        currentEngine.Abort();
93      lock(connectionLock) {
94        if(factory.State == CommunicationState.Opened || factory.State == CommunicationState.Opening) {
95          IAsyncResult closeResult = factory.BeginClose(null, null);
96          factory.EndClose(closeResult);
97        }
98      }
99      statusTextBox.Text = "Stopped";
100      stopButton.Enabled = false;
101      startButton.Enabled = true;
102    }
103
104    private void fetchOperationTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
105      byte[] engineXml = null;
106      // first stop the timer!
107      fetchOperationTimer.Stop();
108      bool gotEngine = false;
109      lock(connectionLock) {
110        if(stopped) return;
111        try {
112          gotEngine = engineStore.TryTakeEngine(out currentGuid, out engineXml);
113        } catch(TimeoutException) {
114          currentEngine = null;
115          currentGuid = Guid.Empty;
116          // timeout -> just start the timer again
117          fetchOperationTimer.Interval = 5000;
118          fetchOperationTimer.Start();
119        } catch(CommunicationException) {
120          // connection problem -> reset connection and start the timer again
121          ResetConnection();
122          currentEngine = null;
123          currentGuid = Guid.Empty;
124          fetchOperationTimer.Interval = 5000;
125          fetchOperationTimer.Start();
126        }
127      }
128      // got engine from server and user didn't press stop -> execute the engine
129      if(gotEngine && !stopped) {
130        currentEngine = RestoreEngine(engineXml);
131        if(InvokeRequired) { Invoke((MethodInvoker)delegate() { statusTextBox.Text = "Executing engine"; }); } else statusTextBox.Text = "Executing engine";
132        currentEngine.Finished += new EventHandler(currentEngine_Finished); // register event-handler that sends result back to server and restarts timer
133        currentEngine.Execute();
134      } else {
135        // ok we didn't get engine -> if the user didn't press stop this means that the server doesn't have engines for us
136        // if the user pressed stop we must not start the timer
137        if(!stopped) {
138          if(InvokeRequired) { Invoke((MethodInvoker)delegate() { statusTextBox.Text = "Waiting for engine"; }); } else statusTextBox.Text = "Waiting for engine";
139          // start the timer again
140          fetchOperationTimer.Interval = 5000;
141          fetchOperationTimer.Start();
142        }
143      }
144    }
145
146    void currentEngine_Finished(object sender, EventArgs e) {
147      IEngine engine = (IEngine)sender;
148      byte[] resultXml = SaveEngine(engine);
149      bool success = false;
150      int retries = 0;
151      do {
152        lock(connectionLock) {
153          if(!stopped) {
154            try {
155              engineStore.StoreResult(currentGuid, resultXml);
156              success = true;
157            } catch(TimeoutException) {
158              success = false;
159              retries++;
160              Thread.Sleep(TimeSpan.FromSeconds(CONNECTION_RETRY_TIMEOUT_SEC));
161            } catch(CommunicationException) {
162              ResetConnection();
163              success = false;
164              retries++;
165              Thread.Sleep(TimeSpan.FromSeconds(CONNECTION_RETRY_TIMEOUT_SEC));
166            }
167          }
168        }
169      } while(!stopped && !success && retries < MAX_RETRIES);
170      // ok if we could store the result it's probable that the server can send us another engine use a small time-interval
171      if(success)
172        fetchOperationTimer.Interval = 100;
173      else fetchOperationTimer.Interval = CONNECTION_RETRY_TIMEOUT_SEC; // if there were problems -> sleep for a longer time
174      // clear state
175      currentEngine = null;
176      currentGuid = Guid.Empty;
177      // start the timer
178      fetchOperationTimer.Start();
179    }
180
181    private ProcessingEngine RestoreEngine(byte[] engine) {
182      GZipStream stream = new GZipStream(new MemoryStream(engine), CompressionMode.Decompress);
183      return (ProcessingEngine)PersistenceManager.Load(stream);
184    }
185    private byte[] SaveEngine(IEngine engine) {
186      MemoryStream memStream = new MemoryStream();
187      GZipStream stream = new GZipStream(memStream, CompressionMode.Compress, true);
188      PersistenceManager.Save(engine, stream);
189      stream.Close();
190      return memStream.ToArray();
191    }
192  }
193}
Note: See TracBrowser for help on using the repository browser.