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

Last change on this file since 2527 was 2527, checked in by nolte, 11 years ago

Added more Information to the Information-Tag of the
StatisticPresentation.

File size: 19.0 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                        statisticTimer = new Timer { Interval = 30 * 60 * 1000 };
99                        statisticTimer.Start();
100                    }
101
102                    status.IsCurrentProgressIndeterminate = true;
103
104                    BigInteger displayablePatternId;
105                    try
106                    {
107                        status.CurrentOperation = Resources.Finding_next_leaf_to_calculate;
108                        currentLeaf = keyPoolTree.FindNextLeaf();
109                        if (currentLeaf == null)
110                        {
111                            break;
112                        }
113                        displayablePatternId = currentLeaf.PatternId() + 1;
114                    }
115                    catch (AlreadyCalculatedException)
116                    {
117                        keySearcher.GuiLogMessage(Resources.Node_was_already_calculated_, NotificationLevel.Info);
118                        keyPoolTree.Reset();
119                        continue;
120                    }
121                    catch (KeySearcherStopException)  //Fullstopfunction
122                    {
123                        keySearcher.GuiLogMessage(Resources.Keysearcher_Fullstop__Please_Update_your_Version_, NotificationLevel.Debug);
124                        status.CurrentOperation = Resources.PLEASE_UPDATE;
125                        keyPoolTree.Reset();
126                        keySearcher.Stop();
127                        return;
128                    }
129
130                    // TODO if reserve returns successfully, start timer to update our reserveration every few minutes
131                    // if we cannot reacquire our lock in the timer, calculation must be aborted
132                    if (!currentLeaf.ReserveLeaf())
133                    {
134                        keySearcher.GuiLogMessage(
135                            string.Format(Resources.Pattern___0__was_reserved_before_it_could_be_reserved_for_this_CrypTool_instance_, displayablePatternId),
136                            NotificationLevel.Info);
137                        keyPoolTree.Reset();
138                        continue;
139                    }
140
141                    bool reservationRemoved = false;
142                    var reservationTimer = new Timer { Interval = 18 * 60 * 1000 };    //Every 18 minutes
143                    reservationTimer.Elapsed += new ElapsedEventHandler(delegate
144                                                                            {
145                                                                                var oldMessage = status.CurrentOperation;
146                                                                                var message = string.Format(Resources.Rereserving_pattern___0_, displayablePatternId);
147                                                                                keySearcher.GuiLogMessage(message, NotificationLevel.Info);
148                                                                                status.CurrentOperation = message;
149                                                                                try
150                                                                                {
151                                                                                    if (!currentLeaf.ReserveLeaf())
152                                                                                        keySearcher.GuiLogMessage(Resources.Rereserving_pattern_failed_, NotificationLevel.Warning);
153
154                                                                                    //if (!currentLeaf.ReserveLeaf())
155                                                                                    //{
156                                                                                    //    keySearcher.GuiLogMessage("Rereserving pattern failed! Skipping to next pattern!",
157                                                                                    //        NotificationLevel.Warning);
158                                                                                    //    reservationRemoved = true;
159                                                                                    //    keySearcher.stop = true;
160                                                                                    //}
161                                                                                }
162                                                                                catch (Cryptool.P2P.Internal.NotConnectedException)
163                                                                                {
164                                                                                    keySearcher.GuiLogMessage(Resources.Rereserving_pattern_failed__because_there_is_no_connection_,
165                                                                                            NotificationLevel.Warning);
166                                                                                    //TODO: Register OnSystemJoined event to rereserve pattern immediately after reconnect
167                                                                                }
168                                                                                status.CurrentOperation = oldMessage;
169                                                                            });
170
171                    statisticTimer.Elapsed += new ElapsedEventHandler(delegate
172                                                                          {
173                                                                              statupdate = true;
174                                                                          });
175
176                    keySearcher.GuiLogMessage(
177                        string.Format(Resources.Running_pattern___0__of__1_, displayablePatternId, patternPool.Length),
178                        NotificationLevel.Info);
179                    status.CurrentChunk = displayablePatternId;
180                    status.CurrentOperation = Resources.Calculating_pattern_ + status.CurrentChunk;
181
182                    try
183                    {
184                        LinkedList<KeySearcher.ValueKey> result;
185
186                        status.IsCurrentProgressIndeterminate = false;
187                        StopWatch.Start();
188                        reservationTimer.Start();
189                        try
190                        {
191                            result = keySearcher.BruteForceWithLocalSystem(patternPool[currentLeaf.PatternId()], true);
192                            if (reservationRemoved)
193                            {
194                                keySearcher.stop = false;
195                                throw new ReservationRemovedException("");
196                            }
197                        }
198                        finally
199                        {
200                            reservationTimer.Stop();
201                            reservationTimer.Dispose();
202                            StopWatch.Stop();
203                            status.IsCurrentProgressIndeterminate = true;
204                        }
205
206                        if (!keySearcher.stop)
207                        {
208                            if (!P2PManager.IsConnected)
209                            {
210                                status.CurrentOperation = Resources.Connection_lost__Waiting_for_reconnection_to_store_the_results_;
211                                keySearcher.GuiLogMessage(status.CurrentOperation, NotificationLevel.Info);
212                                do
213                                {
214                                    P2PManager.P2PBase.OnSystemJoined += P2PBase_OnSystemJoined;
215                                    systemJoinEvent.WaitOne(1000);
216                                } while (!P2PManager.IsConnected);
217                            }
218                            status.CurrentOperation = Resources.Processing_results_of_calculation;
219
220                            String hostname = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetHostName();
221                            Int64 hostid = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetID();
222                            if (settings.UseExternalClient)
223                            {
224                                hostname = keySearcher.ExternalClientHostname;
225                                hostid = keySearcher.ExternaClientId;
226                            }
227                            KeyPoolTree.ProcessCurrentPatternCalculationResult(currentLeaf, result, hostid, hostname);
228                            StatisticsGenerator.ProcessPatternResults(result);
229
230                            status.CurrentOperation = Resources.Calculating_global_statistics;
231                            StatisticsGenerator.CalculateGlobalStatistics(displayablePatternId);
232
233                            status.LocalFinishedChunks++;
234                            keySearcher.GuiLogMessage(
235                                string.Format(Resources.Best_match___0__with__1_, result.First.Value.key, result.First.Value.value),
236                                NotificationLevel.Info);
237
238                            status.CurrentOperation = Resources.Updating_status_in_DHT;
239                            keyPoolTree.UpdateStatus(currentLeaf);
240                        }
241                        else
242                        {
243                            keySearcher.GuiLogMessage(Resources.Brute_force_was_stopped__not_saving_results___,
244                                                      NotificationLevel.Info);
245                            status.ProgressOfCurrentChunk = 0;
246                            currentLeaf.GiveLeafFree();
247                            var message = string.Format(Resources.Removed_reservation_of_pattern___0_, displayablePatternId);
248                            keySearcher.GuiLogMessage(message, NotificationLevel.Info);
249                            status.CurrentOperation = message;
250                        }
251                    }
252                    catch (ReservationRemovedException)
253                    {
254                        keySearcher.GuiLogMessage(Resources.Reservation_removed_by_another_node__while_calculating___To_avoid_a_state_in_limbo__proceeding_to_first_available_leaf___,
255                                                  NotificationLevel.Info);
256                        keyPoolTree.Reset();
257                        continue;
258                    }
259                    catch (UpdateFailedException e)
260                    {
261                        keySearcher.GuiLogMessage(Resources.Could_not_store_results__ + e.Message, NotificationLevel.Info);
262                        keyPoolTree.Reset();
263                        continue;
264                    }
265                    catch (KeySearcherStopException)  //Fullstopfunction
266                    {
267                        keySearcher.GuiLogMessage(Resources.Keysearcher_Fullstop__Please_Update_your_Version_, NotificationLevel.Debug);
268                        status.CurrentOperation = Resources.PLEASE_UPDATE;
269                        keyPoolTree.Reset();
270                        keySearcher.Stop();
271                        return;
272                    }
273
274                    // Push statistics to database
275                    status.CurrentOperation = Resources.Pushing_statistics_to_evaluation_database;
276                    DatabaseStatistics.PushToDatabase(status, StopWatch.ElapsedMilliseconds, keyPoolTree.Identifier, settings, keySearcher);
277                }
278                catch (NotConnectedException)
279                {
280                    status.CurrentOperation = "Connection lost. Waiting for reconnect...";
281                    keySearcher.GuiLogMessage(status.CurrentOperation, NotificationLevel.Info);
282                    do
283                    {
284                        P2PManager.P2PBase.OnSystemJoined += P2PBase_OnSystemJoined;
285                        systemJoinEvent.WaitOne(1000);
286                    } while (!P2PManager.IsConnected);
287                }
288                catch (InvalidOperationException)
289                {
290                    //do nothing
291                }
292            }
293
294            // Set progress to 100%
295            if (!keySearcher.stop && keyPoolTree.IsCalculationFinished())
296            {
297                keySearcher.showProgress(keySearcher.costList, 1, 1, 1);
298                keySearcher.GuiLogMessage(Resources.Calculation_complete_, NotificationLevel.Info);
299                keyPoolTree.UpdateStatusForFinishedCalculation();
300            }
301
302            StatisticsGenerator.CalculationStopped();
303            status.ProgressOfCurrentChunk = 0;
304            status.IsSearchingForReservedNodes = false;
305            status.IsCurrentProgressIndeterminate = false;
306            status.CurrentOperation = "Idle";
307            statisticTimer.Stop();
308            statisticTimer.Dispose();
309            status.RemainingTimeTotal = new TimeSpan(0);
310        }
311
312        private int FindLocalPatterns()
313        {
314            //String myAvatar = "CrypTool2";
315            String myAvatar = P2PSettings.Default.PeerName;
316            long myID = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetID();
317            Dictionary<string, Dictionary<long, Information>> myStats = keySearcher.GetStatistics();
318
319            if(myStats.ContainsKey(myAvatar))
320            {
321                if(myStats[myAvatar].ContainsKey(myID))
322                {
323                    return myStats[myAvatar][myID].Count;
324                }
325            }
326            return 0;
327        }
328
329        private void InitializeTree()
330        {
331            try
332            {
333                keyPoolTree = new KeyPoolTree(patternPool, keySearcher, keyQualityHelper, keyGenerator, status, StatisticsGenerator);
334            }
335            catch (KeySearcherStopException)
336            {
337                status.CurrentOperation = Resources.PLEASE_UPDATE;
338                keySearcher.GuiLogMessage(Resources.Keysearcher_Fullstop__Please_Update_your_Version_, NotificationLevel.Error);
339                keySearcher.Stop();
340                throw new KeySearcherStopException();
341            }
342
343
344            keySearcher.GuiLogMessage(
345                string.Format(Resources.Total_amount_of_patterns___0___each_containing__1__keys_, patternPool.Length, patternPool.PartSize), NotificationLevel.Info);
346            status.CurrentOperation = Resources.Ready_for_calculation;
347
348            status.StartDate = keyPoolTree.StartDate();
349            keySearcher.SetBeginningDate(keyPoolTree.StartDate());
350            status.JobSubmitterID = keyPoolTree.SubmitterID();
351            status.LocalFinishedChunks = FindLocalPatterns();
352
353            keyPoolTree.UpdateStatusForNewCalculation();
354            keySearcher.SetInitialized(true);
355        }
356
357        void P2PBase_OnSystemJoined()
358        {
359            P2PManager.P2PBase.OnSystemJoined -= P2PBase_OnSystemJoined;
360            systemJoinEvent.Set();
361        }
362
363        private void UpdateStatusContainerInQuickWatch()
364        {
365            quickWatch.DataContext = status;
366            quickWatch.UpdateSettings(keySearcher, settings);
367        }
368    }
369}
Note: See TracBrowser for help on using the repository browser.