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

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

statistic update: every 30 minutes the statistics will be updated automatically
to the exact statistics.

File size: 16.7 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 System.Timers;
19using Timer = System.Timers.Timer;
20
21namespace KeySearcher.P2P
22{
23    internal class DistributedBruteForceManager
24    {
25        private readonly StorageKeyGenerator keyGenerator;
26        private readonly KeySearcher keySearcher;
27        private readonly KeySearcherSettings settings;
28        private readonly KeyQualityHelper keyQualityHelper;
29        private readonly P2PQuickWatchPresentation quickWatch;
30        private readonly KeyPatternPool patternPool;
31        private readonly StatusContainer status;
32        internal readonly StatisticsGenerator StatisticsGenerator;
33        internal readonly Stopwatch StopWatch;
34
35        private KeyPoolTree keyPoolTree;
36        private AutoResetEvent systemJoinEvent = new AutoResetEvent(false);
37
38        public DistributedBruteForceManager(KeySearcher keySearcher, KeyPattern.KeyPattern keyPattern, KeySearcherSettings settings,
39                                            KeyQualityHelper keyQualityHelper, P2PQuickWatchPresentation quickWatch)
40        {
41            this.keySearcher = keySearcher;
42            this.settings = settings;
43            this.keyQualityHelper = keyQualityHelper;
44            this.quickWatch = quickWatch;
45
46            // TODO when setting is still default (21), it is only displayed as 21 - but the settings-instance contains 0 for that key!
47            if (settings.ChunkSize == 0)
48            {
49                settings.ChunkSize = 21;
50            }
51
52            StopWatch = new Stopwatch();
53            status = new StatusContainer(keySearcher);
54            status.IsCurrentProgressIndeterminate = true;
55
56            keyGenerator = new StorageKeyGenerator(keySearcher, settings);
57            patternPool = new KeyPatternPool(keyPattern, new BigInteger(Math.Pow(2, settings.ChunkSize)));
58            StatisticsGenerator = new StatisticsGenerator(status, quickWatch, keySearcher, settings, this);
59            quickWatch.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(UpdateStatusContainerInQuickWatch));
60        }
61
62        public void Execute()
63        {
64            status.CurrentOperation = "Initializing connection to the peer-to-peer system";
65            new ConnectionHelper(keySearcher, settings).ValidateConnectionToPeerToPeerSystem();
66
67            if (!P2PManager.IsConnected)
68            {
69                keySearcher.GuiLogMessage("Unable to use peer-to-peer system.", NotificationLevel.Error);
70                status.CurrentOperation = "Unable to use peer-to-peer system";
71                return;
72            }
73
74            status.CurrentOperation = "Initializing distributed key pool tree";
75            InitializeTree();
76           
77            bool statupdate = false;
78            Leaf currentLeaf;
79            var statisticTimer = new Timer { Interval = 30 * 60 * 1000 };    //Update of the statistics after every 30 minutes
80            statisticTimer.Start();
81
82            while (!keySearcher.stop)
83            {
84                if(statupdate)
85                {
86                    statisticTimer.Stop();
87                    statisticTimer.Dispose();
88                    keyPoolTree.Reset();
89                    keySearcher.ResetStatistics();
90                    keySearcher.SetInitialized(false);
91                    status.CurrentOperation = "Updating statistic";
92                    InitializeTree();
93                    statupdate = false;
94                    statisticTimer = new Timer { Interval = 30 * 60 * 1000 };
95                    statisticTimer.Start();
96                }
97
98                status.IsCurrentProgressIndeterminate = true;
99
100                BigInteger displayablePatternId;
101                try
102                {
103                    status.CurrentOperation = "Finding next leaf to calculate";
104                    currentLeaf = keyPoolTree.FindNextLeaf();
105                    if (currentLeaf == null)
106                    {
107                        break;
108                    }
109                    displayablePatternId = currentLeaf.PatternId() + 1;
110                }
111                catch (AlreadyCalculatedException)
112                {
113                    keySearcher.GuiLogMessage("Node was already calculated.", NotificationLevel.Info);
114                    keyPoolTree.Reset();
115                    continue;
116                }
117                catch (KeySearcherStopException)  //Fullstopfunction
118                {
119                    keySearcher.GuiLogMessage("Keysearcher Fullstop.Please Update your Version.", NotificationLevel.Debug);
120                    status.CurrentOperation = "PLEASE UPDATE";
121                    keyPoolTree.Reset();
122                    keySearcher.Stop();
123                    return;
124                }
125
126                // TODO if reserve returns successfully, start timer to update our reserveration every few minutes
127                // if we cannot reacquire our lock in the timer, calculation must be aborted
128                if (!currentLeaf.ReserveLeaf())
129                {
130                    keySearcher.GuiLogMessage(
131                        "Pattern #" + displayablePatternId +
132                        " was reserved before it could be reserved for this CrypTool instance.",
133                        NotificationLevel.Info);
134                    keyPoolTree.Reset();
135                    continue;
136                }
137
138                bool reservationRemoved = false;
139                var reservationTimer = new Timer {Interval = 5*60*1000};    //Every 5 minutes
140                reservationTimer.Elapsed += new ElapsedEventHandler(delegate
141                                                                        {
142                                                                            var oldMessage = status.CurrentOperation;
143                                                                            var message = string.Format("Rereserving pattern #{0}", displayablePatternId);
144                                                                            keySearcher.GuiLogMessage(message, NotificationLevel.Info);
145                                                                            status.CurrentOperation = message;
146                                                                            try
147                                                                            {
148                                                                                if (!currentLeaf.ReserveLeaf())
149                                                                                    keySearcher.GuiLogMessage("Rereserving pattern failed!", NotificationLevel.Warning);
150
151                                                                                //if (!currentLeaf.ReserveLeaf())
152                                                                                //{
153                                                                                //    keySearcher.GuiLogMessage("Rereserving pattern failed! Skipping to next pattern!",
154                                                                                //        NotificationLevel.Warning);
155                                                                                //    reservationRemoved = true;
156                                                                                //    keySearcher.stop = true;
157                                                                                //}
158                                                                            }
159                                                                            catch (Cryptool.P2P.Internal.NotConnectedException)
160                                                                            {
161                                                                                keySearcher.GuiLogMessage("Rereserving pattern failed, because there is no connection!",
162                                                                                        NotificationLevel.Warning);
163                                                                                //TODO: Register OnSystemJoined event to rereserve pattern immediately after reconnect
164                                                                            }
165                                                                            status.CurrentOperation = oldMessage;
166                                                                        });
167
168                statisticTimer.Elapsed += new ElapsedEventHandler(delegate
169                                                                      {
170                                                                          statupdate = true;
171                                                                      });
172
173                keySearcher.GuiLogMessage(
174                    "Running pattern #" + displayablePatternId + " of " + patternPool.Length,
175                    NotificationLevel.Info);
176                status.CurrentChunk = displayablePatternId;
177                status.CurrentOperation = "Calculating pattern " + status.CurrentChunk;
178
179                try
180                {
181                    LinkedList<KeySearcher.ValueKey> result;
182
183                    status.IsCurrentProgressIndeterminate = false;
184                    StopWatch.Start();
185                    reservationTimer.Start();
186                    try
187                    {
188                        result = keySearcher.BruteForceWithLocalSystem(patternPool[currentLeaf.PatternId()], true);
189                        if (reservationRemoved)
190                        {
191                            keySearcher.stop = false;
192                            throw new ReservationRemovedException("");
193                        }
194                    }
195                    finally
196                    {
197                        reservationTimer.Stop();
198                        reservationTimer.Dispose();
199                        StopWatch.Stop();
200                        status.IsCurrentProgressIndeterminate = true;
201                    }
202
203                    if (!keySearcher.stop)
204                    {
205                        if (!P2PManager.IsConnected)
206                        {
207                            status.CurrentOperation = "Connection lost! Waiting for reconnection to store the results!";
208                            keySearcher.GuiLogMessage(status.CurrentOperation, NotificationLevel.Info);
209                           
210                            P2PManager.P2PBase.OnSystemJoined += new P2PBase.SystemJoined(P2PBase_OnSystemJoined);
211                            systemJoinEvent.WaitOne();
212                        }
213                        status.CurrentOperation = "Processing results of calculation";
214                        KeyPoolTree.ProcessCurrentPatternCalculationResult(currentLeaf, result);
215                        StatisticsGenerator.ProcessPatternResults(result);
216
217                        status.CurrentOperation = "Calculating global statistics";
218                        StatisticsGenerator.CalculateGlobalStatistics(displayablePatternId);
219
220                        status.LocalFinishedChunks++;
221                        keySearcher.GuiLogMessage(
222                            string.Format("Best match: {0} with {1}", result.First.Value.key, result.First.Value.value),
223                            NotificationLevel.Info);
224
225                        status.CurrentOperation = "Updating status in DHT";
226                        keyPoolTree.UpdateStatus(currentLeaf);
227                    }
228                    else
229                    {
230                        keySearcher.GuiLogMessage("Brute force was stopped, not saving results...",
231                                                  NotificationLevel.Info);
232                        status.ProgressOfCurrentChunk = 0;
233                        currentLeaf.GiveLeafFree();
234                        var message = string.Format("Removed reservation of pattern #{0}", displayablePatternId);
235                        keySearcher.GuiLogMessage(message, NotificationLevel.Info);
236                        status.CurrentOperation = message;
237                    }
238                }
239                catch (ReservationRemovedException)
240                {
241                    keySearcher.GuiLogMessage("Reservation removed by another node (while calculating). " +
242                                              "To avoid a state in limbo, proceeding to first available leaf...",
243                                              NotificationLevel.Info);
244                    keyPoolTree.Reset();
245                    continue;
246                }
247                catch (UpdateFailedException e)
248                {
249                    keySearcher.GuiLogMessage("Could not store results: " + e.Message, NotificationLevel.Info);
250                    keyPoolTree.Reset();
251                    continue;
252                }
253                catch (KeySearcherStopException)  //Fullstopfunction
254                {
255                    keySearcher.GuiLogMessage("Keysearcher Fullstop.Please Update your Version.", NotificationLevel.Debug);
256                    status.CurrentOperation = "PLEASE UPDATE";
257                    keyPoolTree.Reset();
258                    keySearcher.Stop();
259                    return;
260                }
261
262                // Push statistics to database
263                status.CurrentOperation = "Pushing statistics to evaluation database";
264                DatabaseStatistics.PushToDatabase(status, StopWatch.ElapsedMilliseconds, keyPoolTree.Identifier, settings, keySearcher);
265            }
266
267            // Set progress to 100%
268            if (!keySearcher.stop && keyPoolTree.IsCalculationFinished())
269            {
270                keySearcher.showProgress(keySearcher.costList, 1, 1, 1);
271                keySearcher.GuiLogMessage("Calculation complete.", NotificationLevel.Info);
272                keyPoolTree.UpdateStatusForFinishedCalculation();
273            }
274
275            StatisticsGenerator.CalculationStopped();
276            status.ProgressOfCurrentChunk = 0;
277            status.IsSearchingForReservedNodes = false;
278            status.IsCurrentProgressIndeterminate = false;
279            status.CurrentOperation = "Idle";
280            statisticTimer.Stop();
281            statisticTimer.Dispose();
282            status.RemainingTimeTotal = new TimeSpan(0);
283        }
284
285        private int FindLocalPatterns()
286        {
287            //String myAvatar = "CrypTool2";
288            String myAvatar = P2PSettings.Default.PeerName;
289            long myID = Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetID();
290            Dictionary<string, Dictionary<long, Information>> myStats = keySearcher.GetStatistics();
291
292            if(myStats.ContainsKey(myAvatar))
293            {
294                if(myStats[myAvatar].ContainsKey(myID))
295                {
296                    return myStats[myAvatar][myID].Count;
297                }
298            }
299            return 0;
300        }
301
302        private void InitializeTree()
303        {
304            try
305            {
306                keyPoolTree = new KeyPoolTree(patternPool, keySearcher, keyQualityHelper, keyGenerator, status, StatisticsGenerator);
307            }
308            catch (KeySearcherStopException)
309            {
310                status.CurrentOperation = "PLEASE UPDATE";
311                keySearcher.GuiLogMessage("Keysearcher Fullstop.Please Update your Version.", NotificationLevel.Error);
312                keySearcher.Stop();
313                throw new KeySearcherStopException();
314            }
315
316
317            keySearcher.GuiLogMessage(
318                "Total amount of patterns: " + patternPool.Length + ", each containing " + patternPool.PartSize +
319                " keys.", NotificationLevel.Info);
320            status.CurrentOperation = "Ready for calculation";
321
322            status.StartDate = keyPoolTree.StartDate();
323            status.JobSubmitterID = keyPoolTree.SubmitterID();
324            status.LocalFinishedChunks = FindLocalPatterns();
325
326            keyPoolTree.UpdateStatusForNewCalculation();
327            keySearcher.SetInitialized(true);
328        }
329
330        void P2PBase_OnSystemJoined()
331        {
332            P2PManager.P2PBase.OnSystemJoined -= P2PBase_OnSystemJoined;
333            systemJoinEvent.Set();
334        }
335
336        private void UpdateStatusContainerInQuickWatch()
337        {
338            quickWatch.DataContext = status;
339            quickWatch.UpdateSettings(keySearcher, settings);
340        }
341    }
342}
Note: See TracBrowser for help on using the repository browser.