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

Last change on this file since 2495 was 2495, checked in by schwittmann, 11 years ago

Display external clients in statistics

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