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

Last change on this file since 2436 was 2436, checked in by Sven Rech, 10 years ago

make keysearcher more robust

File size: 18.3 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                            KeyPoolTree.ProcessCurrentPatternCalculationResult(currentLeaf, result);
219                            StatisticsGenerator.ProcessPatternResults(result);
220
221                            status.CurrentOperation = Resources.Calculating_global_statistics;
222                            StatisticsGenerator.CalculateGlobalStatistics(displayablePatternId);
223
224                            status.LocalFinishedChunks++;
225                            keySearcher.GuiLogMessage(
226                                string.Format(Resources.Best_match___0__with__1_, result.First.Value.key, result.First.Value.value),
227                                NotificationLevel.Info);
228
229                            status.CurrentOperation = Resources.Updating_status_in_DHT;
230                            keyPoolTree.UpdateStatus(currentLeaf);
231                        }
232                        else
233                        {
234                            keySearcher.GuiLogMessage(Resources.Brute_force_was_stopped__not_saving_results___,
235                                                      NotificationLevel.Info);
236                            status.ProgressOfCurrentChunk = 0;
237                            currentLeaf.GiveLeafFree();
238                            var message = string.Format(Resources.Removed_reservation_of_pattern___0_, displayablePatternId);
239                            keySearcher.GuiLogMessage(message, NotificationLevel.Info);
240                            status.CurrentOperation = message;
241                        }
242                    }
243                    catch (ReservationRemovedException)
244                    {
245                        keySearcher.GuiLogMessage(Resources.Reservation_removed_by_another_node__while_calculating___To_avoid_a_state_in_limbo__proceeding_to_first_available_leaf___,
246                                                  NotificationLevel.Info);
247                        keyPoolTree.Reset();
248                        continue;
249                    }
250                    catch (UpdateFailedException e)
251                    {
252                        keySearcher.GuiLogMessage(Resources.Could_not_store_results__ + e.Message, NotificationLevel.Info);
253                        keyPoolTree.Reset();
254                        continue;
255                    }
256                    catch (KeySearcherStopException)  //Fullstopfunction
257                    {
258                        keySearcher.GuiLogMessage(Resources.Keysearcher_Fullstop__Please_Update_your_Version_, NotificationLevel.Debug);
259                        status.CurrentOperation = Resources.PLEASE_UPDATE;
260                        keyPoolTree.Reset();
261                        keySearcher.Stop();
262                        return;
263                    }
264
265                    // Push statistics to database
266                    status.CurrentOperation = Resources.Pushing_statistics_to_evaluation_database;
267                    DatabaseStatistics.PushToDatabase(status, StopWatch.ElapsedMilliseconds, keyPoolTree.Identifier, settings, keySearcher);
268                }
269                catch (NotConnectedException)
270                {
271                    status.CurrentOperation = "Connection lost. Waiting for reconnect...";
272                    keySearcher.GuiLogMessage(status.CurrentOperation, NotificationLevel.Info);
273                    do
274                    {
275                        P2PManager.P2PBase.OnSystemJoined += P2PBase_OnSystemJoined;
276                        systemJoinEvent.WaitOne(1000);
277                    } while (!P2PManager.IsConnected);
278                }
279            }
280
281            // Set progress to 100%
282            if (!keySearcher.stop && keyPoolTree.IsCalculationFinished())
283            {
284                keySearcher.showProgress(keySearcher.costList, 1, 1, 1);
285                keySearcher.GuiLogMessage(Resources.Calculation_complete_, NotificationLevel.Info);
286                keyPoolTree.UpdateStatusForFinishedCalculation();
287            }
288
289            StatisticsGenerator.CalculationStopped();
290            status.ProgressOfCurrentChunk = 0;
291            status.IsSearchingForReservedNodes = false;
292            status.IsCurrentProgressIndeterminate = false;
293            status.CurrentOperation = "Idle";
294            statisticTimer.Stop();
295            statisticTimer.Dispose();
296            status.RemainingTimeTotal = new TimeSpan(0);
297        }
298
299        private int FindLocalPatterns()
300        {
301            //String myAvatar = "CrypTool2";
302            String myAvatar = P2PSettings.Default.PeerName;
303            long myID = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetID();
304            Dictionary<string, Dictionary<long, Information>> myStats = keySearcher.GetStatistics();
305
306            if(myStats.ContainsKey(myAvatar))
307            {
308                if(myStats[myAvatar].ContainsKey(myID))
309                {
310                    return myStats[myAvatar][myID].Count;
311                }
312            }
313            return 0;
314        }
315
316        private void InitializeTree()
317        {
318            try
319            {
320                keyPoolTree = new KeyPoolTree(patternPool, keySearcher, keyQualityHelper, keyGenerator, status, StatisticsGenerator);
321            }
322            catch (KeySearcherStopException)
323            {
324                status.CurrentOperation = Resources.PLEASE_UPDATE;
325                keySearcher.GuiLogMessage(Resources.Keysearcher_Fullstop__Please_Update_your_Version_, NotificationLevel.Error);
326                keySearcher.Stop();
327                throw new KeySearcherStopException();
328            }
329
330
331            keySearcher.GuiLogMessage(
332                string.Format(Resources.Total_amount_of_patterns___0___each_containing__1__keys_, patternPool.Length, patternPool.PartSize), NotificationLevel.Info);
333            status.CurrentOperation = Resources.Ready_for_calculation;
334
335            status.StartDate = keyPoolTree.StartDate();
336            status.JobSubmitterID = keyPoolTree.SubmitterID();
337            status.LocalFinishedChunks = FindLocalPatterns();
338
339            keyPoolTree.UpdateStatusForNewCalculation();
340            keySearcher.SetInitialized(true);
341        }
342
343        void P2PBase_OnSystemJoined()
344        {
345            P2PManager.P2PBase.OnSystemJoined -= P2PBase_OnSystemJoined;
346            systemJoinEvent.Set();
347        }
348
349        private void UpdateStatusContainerInQuickWatch()
350        {
351            quickWatch.DataContext = status;
352            quickWatch.UpdateSettings(keySearcher, settings);
353        }
354    }
355}
Note: See TracBrowser for help on using the repository browser.