source: trunk/CrypPlugins/KeySearcher/P2P/DistributedBruteForceManager.cs @ 2685

Last change on this file since 2685 was 2685, checked in by nolte, 11 years ago
  • Gave all Information Elements their values
  • ToolTip over LastTimeUpdated shows NextTimeUpdate
  • Rearranged Information Gui Elements for a better View
File size: 19.1 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Diagnostics;
4using System.Numerics;
5using System.Threading;
6using System.Windows.Threading;
7using Cryptool.P2P;
8using Cryptool.P2P.Internal;
9using Cryptool.PluginBase;
10using KeySearcher.Helper;
11using KeySearcher.KeyPattern;
12using KeySearcher.P2P.Exceptions;
13using KeySearcher.P2P.Helper;
14using KeySearcher.P2P.Presentation;
15using KeySearcher.P2P.Storage;
16using KeySearcher.P2P.Tree;
17using KeySearcherPresentation.Controls;
18using KeySearcher.Properties;
19using System.Timers;
20using Timer = System.Timers.Timer;
21
22namespace KeySearcher.P2P
23{
24    internal class DistributedBruteForceManager
25    {
26        private readonly StorageKeyGenerator keyGenerator;
27        private readonly KeySearcher keySearcher;
28        private readonly KeySearcherSettings settings;
29        private readonly KeyQualityHelper keyQualityHelper;
30        private readonly P2PQuickWatchPresentation quickWatch;
31        private readonly KeyPatternPool patternPool;
32        private readonly StatusContainer status;
33        internal readonly StatisticsGenerator StatisticsGenerator;
34        internal readonly Stopwatch StopWatch;
35
36        private KeyPoolTree keyPoolTree;
37        private AutoResetEvent systemJoinEvent = new AutoResetEvent(false);
38
39        public DistributedBruteForceManager(KeySearcher keySearcher, KeyPattern.KeyPattern keyPattern, KeySearcherSettings settings,
40                                            KeyQualityHelper keyQualityHelper, P2PQuickWatchPresentation quickWatch)
41        {
42            this.keySearcher = keySearcher;
43            this.settings = settings;
44            this.keyQualityHelper = keyQualityHelper;
45            this.quickWatch = quickWatch;
46
47            // TODO when setting is still default (21), it is only displayed as 21 - but the settings-instance contains 0 for that key!
48            if (settings.ChunkSize == 0)
49            {
50                settings.ChunkSize = 21;
51            }
52
53            StopWatch = new Stopwatch();
54            status = new StatusContainer(keySearcher);
55            status.IsCurrentProgressIndeterminate = true;
56
57            keyGenerator = new StorageKeyGenerator(keySearcher, settings);
58            patternPool = new KeyPatternPool(keyPattern, new BigInteger(Math.Pow(2, settings.ChunkSize)));
59            StatisticsGenerator = new StatisticsGenerator(status, quickWatch, keySearcher, settings, this);
60            quickWatch.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(UpdateStatusContainerInQuickWatch));
61        }
62
63        public void Execute()
64        {
65            status.CurrentOperation = Resources.Initializing_connection_to_the_peer_to_peer_system;
66            new ConnectionHelper(keySearcher, settings).ValidateConnectionToPeerToPeerSystem();
67
68            if (!P2PManager.IsConnected)
69            {
70                keySearcher.GuiLogMessage(Resources.Unable_to_use_peer_to_peer_system_, NotificationLevel.Error);
71                status.CurrentOperation = Resources.Unable_to_use_peer_to_peer_system_;
72                return;
73            }
74
75            status.CurrentOperation = Resources.Initializing_distributed_key_pool_tree;
76            InitializeTree();
77           
78            bool statupdate = false;
79            Leaf currentLeaf;
80            keySearcher.InitialiseInformationQuickwatch();
81            var statisticTimer = new Timer { Interval = 30 * 60 * 1000 };    //Update of the statistics after every 30 minutes
82            statisticTimer.Start();
83
84            while (!keySearcher.stop)
85            {
86                try
87                {
88                    if (statupdate)
89                    {
90                        statisticTimer.Stop();
91                        statisticTimer.Dispose();
92                        keyPoolTree.Reset();
93                        keySearcher.ResetStatistics();
94                        keySearcher.SetInitialized(false);
95                        status.CurrentOperation = Resources.Updating_statistic;
96                        InitializeTree();
97                        statupdate = false;
98                        keySearcher.InitialiseInformationQuickwatch();
99                        statisticTimer = new Timer { Interval = 30 * 60 * 1000 };
100                        statisticTimer.Start();
101                    }
102
103                    status.IsCurrentProgressIndeterminate = true;
104
105                    BigInteger displayablePatternId;
106                    try
107                    {
108                        status.CurrentOperation = Resources.Finding_next_leaf_to_calculate;
109                        currentLeaf = keyPoolTree.FindNextLeaf();
110                        if (currentLeaf == null)
111                        {
112                            break;
113                        }
114                        displayablePatternId = currentLeaf.PatternId() + 1;
115                    }
116                    catch (AlreadyCalculatedException)
117                    {
118                        keySearcher.GuiLogMessage(Resources.Node_was_already_calculated_, NotificationLevel.Info);
119                        keyPoolTree.Reset();
120                        continue;
121                    }
122                    catch (KeySearcherStopException)  //Fullstopfunction
123                    {
124                        keySearcher.GuiLogMessage(Resources.Keysearcher_Fullstop__Please_Update_your_Version_, NotificationLevel.Debug);
125                        status.CurrentOperation = Resources.PLEASE_UPDATE;
126                        keyPoolTree.Reset();
127                        keySearcher.Stop();
128                        return;
129                    }
130
131                    // TODO if reserve returns successfully, start timer to update our reserveration every few minutes
132                    // if we cannot reacquire our lock in the timer, calculation must be aborted
133                    if (!currentLeaf.ReserveLeaf())
134                    {
135                        keySearcher.GuiLogMessage(
136                            string.Format(Resources.Pattern___0__was_reserved_before_it_could_be_reserved_for_this_CrypTool_instance_, displayablePatternId),
137                            NotificationLevel.Info);
138                        keyPoolTree.Reset();
139                        continue;
140                    }
141
142                    bool reservationRemoved = false;
143                    var reservationTimer = new Timer { Interval = 18 * 60 * 1000 };    //Every 18 minutes
144                    reservationTimer.Elapsed += new ElapsedEventHandler(delegate
145                                                                            {
146                                                                                var oldMessage = status.CurrentOperation;
147                                                                                var message = string.Format(Resources.Rereserving_pattern___0_, displayablePatternId);
148                                                                                keySearcher.GuiLogMessage(message, NotificationLevel.Info);
149                                                                                status.CurrentOperation = message;
150                                                                                try
151                                                                                {
152                                                                                    if (!currentLeaf.ReserveLeaf())
153                                                                                        keySearcher.GuiLogMessage(Resources.Rereserving_pattern_failed_, NotificationLevel.Warning);
154
155                                                                                    //if (!currentLeaf.ReserveLeaf())
156                                                                                    //{
157                                                                                    //    keySearcher.GuiLogMessage("Rereserving pattern failed! Skipping to next pattern!",
158                                                                                    //        NotificationLevel.Warning);
159                                                                                    //    reservationRemoved = true;
160                                                                                    //    keySearcher.stop = true;
161                                                                                    //}
162                                                                                }
163                                                                                catch (Cryptool.P2P.Internal.NotConnectedException)
164                                                                                {
165                                                                                    keySearcher.GuiLogMessage(Resources.Rereserving_pattern_failed__because_there_is_no_connection_,
166                                                                                            NotificationLevel.Warning);
167                                                                                    //TODO: Register OnSystemJoined event to rereserve pattern immediately after reconnect
168                                                                                }
169                                                                                status.CurrentOperation = oldMessage;
170                                                                            });
171
172                    statisticTimer.Elapsed += new ElapsedEventHandler(delegate
173                                                                          {
174                                                                              statupdate = true;
175                                                                          });
176
177                    keySearcher.GuiLogMessage(
178                        string.Format(Resources.Running_pattern___0__of__1_, displayablePatternId, patternPool.Length),
179                        NotificationLevel.Info);
180                    status.CurrentChunk = displayablePatternId;
181                    status.CurrentOperation = Resources.Calculating_pattern_ + status.CurrentChunk;
182
183                    try
184                    {
185                        LinkedList<KeySearcher.ValueKey> result;
186
187                        status.IsCurrentProgressIndeterminate = false;
188                        StopWatch.Start();
189                        reservationTimer.Start();
190                        try
191                        {
192                            result = keySearcher.BruteForceWithLocalSystem(patternPool[currentLeaf.PatternId()], true);
193                            if (reservationRemoved)
194                            {
195                                keySearcher.stop = false;
196                                throw new ReservationRemovedException("");
197                            }
198                        }
199                        finally
200                        {
201                            reservationTimer.Stop();
202                            reservationTimer.Dispose();
203                            StopWatch.Stop();
204                            status.IsCurrentProgressIndeterminate = true;
205                        }
206
207                        if (!keySearcher.stop)
208                        {
209                            if (!P2PManager.IsConnected)
210                            {
211                                status.CurrentOperation = Resources.Connection_lost__Waiting_for_reconnection_to_store_the_results_;
212                                keySearcher.GuiLogMessage(status.CurrentOperation, NotificationLevel.Info);
213                                do
214                                {
215                                    P2PManager.P2PBase.OnSystemJoined += P2PBase_OnSystemJoined;
216                                    systemJoinEvent.WaitOne(1000);
217                                } while (!P2PManager.IsConnected);
218                            }
219                            status.CurrentOperation = Resources.Processing_results_of_calculation;
220
221                            String hostname = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetHostName();
222                            Int64 hostid = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetID();
223                            if (settings.UseExternalClient)
224                            {
225                                hostname = keySearcher.ExternalClientHostname;
226                                hostid = keySearcher.ExternaClientId;
227                            }
228                            KeyPoolTree.ProcessCurrentPatternCalculationResult(currentLeaf, result, hostid, hostname);
229                            StatisticsGenerator.ProcessPatternResults(result);
230
231                            status.CurrentOperation = Resources.Calculating_global_statistics;
232                            StatisticsGenerator.CalculateGlobalStatistics(displayablePatternId);
233
234                            status.LocalFinishedChunks++;
235                            keySearcher.GuiLogMessage(
236                                string.Format(Resources.Best_match___0__with__1_, result.First.Value.key, result.First.Value.value),
237                                NotificationLevel.Info);
238
239                            status.CurrentOperation = Resources.Updating_status_in_DHT;
240                            keyPoolTree.UpdateStatus(currentLeaf);
241                        }
242                        else
243                        {
244                            keySearcher.GuiLogMessage(Resources.Brute_force_was_stopped__not_saving_results___,
245                                                      NotificationLevel.Info);
246                            status.ProgressOfCurrentChunk = 0;
247                            currentLeaf.GiveLeafFree();
248                            var message = string.Format(Resources.Removed_reservation_of_pattern___0_, displayablePatternId);
249                            keySearcher.GuiLogMessage(message, NotificationLevel.Info);
250                            status.CurrentOperation = message;
251                        }
252                    }
253                    catch (ReservationRemovedException)
254                    {
255                        keySearcher.GuiLogMessage(Resources.Reservation_removed_by_another_node__while_calculating___To_avoid_a_state_in_limbo__proceeding_to_first_available_leaf___,
256                                                  NotificationLevel.Info);
257                        keyPoolTree.Reset();
258                        continue;
259                    }
260                    catch (UpdateFailedException e)
261                    {
262                        keySearcher.GuiLogMessage(Resources.Could_not_store_results__ + e.Message, NotificationLevel.Info);
263                        keyPoolTree.Reset();
264                        continue;
265                    }
266                    catch (KeySearcherStopException)  //Fullstopfunction
267                    {
268                        keySearcher.GuiLogMessage(Resources.Keysearcher_Fullstop__Please_Update_your_Version_, NotificationLevel.Debug);
269                        status.CurrentOperation = Resources.PLEASE_UPDATE;
270                        keyPoolTree.Reset();
271                        keySearcher.Stop();
272                        return;
273                    }
274
275                    // Push statistics to database
276                    status.CurrentOperation = Resources.Pushing_statistics_to_evaluation_database;
277                    DatabaseStatistics.PushToDatabase(status, StopWatch.ElapsedMilliseconds, keyPoolTree.Identifier, settings, keySearcher);
278                }
279                catch (NotConnectedException)
280                {
281                    status.CurrentOperation = "Connection lost. Waiting for reconnect...";
282                    keySearcher.GuiLogMessage(status.CurrentOperation, NotificationLevel.Info);
283                    do
284                    {
285                        P2PManager.P2PBase.OnSystemJoined += P2PBase_OnSystemJoined;
286                        systemJoinEvent.WaitOne(1000);
287                    } while (!P2PManager.IsConnected);
288                }
289                catch (InvalidOperationException)
290                {
291                    //do nothing
292                }
293            }
294
295            // Set progress to 100%
296            if (!keySearcher.stop && keyPoolTree.IsCalculationFinished())
297            {
298                keySearcher.showProgress(keySearcher.costList, 1, 1, 1);
299                keySearcher.GuiLogMessage(Resources.Calculation_complete_, NotificationLevel.Info);
300                keyPoolTree.UpdateStatusForFinishedCalculation();
301            }
302
303            StatisticsGenerator.CalculationStopped();
304            status.ProgressOfCurrentChunk = 0;
305            status.IsSearchingForReservedNodes = false;
306            status.IsCurrentProgressIndeterminate = false;
307            status.CurrentOperation = "Idle";
308            statisticTimer.Stop();
309            statisticTimer.Dispose();
310            status.RemainingTimeTotal = new TimeSpan(0);
311        }
312
313        private int FindLocalPatterns()
314        {
315            //String myAvatar = "CrypTool2";
316            String myAvatar = P2PSettings.Default.PeerName;
317            long myID = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetID();
318            Dictionary<string, Dictionary<long, Information>> myStats = keySearcher.GetStatistics();
319
320            if(myStats.ContainsKey(myAvatar))
321            {
322                if(myStats[myAvatar].ContainsKey(myID))
323                {
324                    return myStats[myAvatar][myID].Count;
325                }
326            }
327            return 0;
328        }
329
330        private void InitializeTree()
331        {
332            try
333            {
334                keyPoolTree = new KeyPoolTree(patternPool, keySearcher, keyQualityHelper, keyGenerator, status, StatisticsGenerator);
335            }
336            catch (KeySearcherStopException)
337            {
338                status.CurrentOperation = Resources.PLEASE_UPDATE;
339                keySearcher.GuiLogMessage(Resources.Keysearcher_Fullstop__Please_Update_your_Version_, NotificationLevel.Error);
340                keySearcher.Stop();
341                throw new KeySearcherStopException();
342            }
343
344
345            keySearcher.GuiLogMessage(
346                string.Format(Resources.Total_amount_of_patterns___0___each_containing__1__keys_, patternPool.Length, patternPool.PartSize), NotificationLevel.Info);
347            status.CurrentOperation = Resources.Ready_for_calculation;
348
349            status.StartDate = keyPoolTree.StartDate();
350            keySearcher.SetBeginningDate(keyPoolTree.StartDate());
351            status.JobSubmitterID = keyPoolTree.SubmitterID();
352            status.LocalFinishedChunks = FindLocalPatterns();
353
354            keyPoolTree.UpdateStatusForNewCalculation();
355            keySearcher.SetInitialized(true);
356        }
357
358        void P2PBase_OnSystemJoined()
359        {
360            P2PManager.P2PBase.OnSystemJoined -= P2PBase_OnSystemJoined;
361            systemJoinEvent.Set();
362        }
363
364        private void UpdateStatusContainerInQuickWatch()
365        {
366            quickWatch.DataContext = status;
367            quickWatch.UpdateSettings(keySearcher, settings);
368        }
369    }
370}
Note: See TracBrowser for help on using the repository browser.