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

Last change on this file since 2434 was 2434, checked in by Sven Rech, 11 years ago

some changes concerning reconnection (I hope this doesn't make things worse)

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