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

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

Versionnumber added. (Not in use yet)
Required whenever the size of the Memory Stream changes.

File size: 11.0 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Diagnostics;
4using System.Numerics;
5using System.Windows.Threading;
6using Cryptool.P2P;
7using Cryptool.PluginBase;
8using KeySearcher.Helper;
9using KeySearcher.KeyPattern;
10using KeySearcher.P2P.Exceptions;
11using KeySearcher.P2P.Helper;
12using KeySearcher.P2P.Presentation;
13using KeySearcher.P2P.Storage;
14using KeySearcher.P2P.Tree;
15using KeySearcherPresentation.Controls;
16using System.Timers;
17
18namespace KeySearcher.P2P
19{
20    internal class DistributedBruteForceManager
21    {
22        private readonly StorageKeyGenerator keyGenerator;
23        private readonly KeySearcher keySearcher;
24        private readonly KeySearcherSettings settings;
25        private readonly KeyQualityHelper keyQualityHelper;
26        private readonly P2PQuickWatchPresentation quickWatch;
27        private readonly KeyPatternPool patternPool;
28        private readonly StatusContainer status;
29        internal readonly StatisticsGenerator StatisticsGenerator;
30        internal readonly Stopwatch StopWatch;
31
32        private KeyPoolTree keyPoolTree;
33
34        public DistributedBruteForceManager(KeySearcher keySearcher, KeyPattern.KeyPattern keyPattern, KeySearcherSettings settings,
35                                            KeyQualityHelper keyQualityHelper, P2PQuickWatchPresentation quickWatch)
36        {
37            this.keySearcher = keySearcher;
38            this.settings = settings;
39            this.keyQualityHelper = keyQualityHelper;
40            this.quickWatch = quickWatch;
41
42            // TODO when setting is still default (21), it is only displayed as 21 - but the settings-instance contains 0 for that key!
43            if (settings.ChunkSize == 0)
44            {
45                settings.ChunkSize = 21;
46            }
47
48            StopWatch = new Stopwatch();
49            status = new StatusContainer(keySearcher);
50            status.IsCurrentProgressIndeterminate = true;
51
52            keyGenerator = new StorageKeyGenerator(keySearcher, settings);
53            patternPool = new KeyPatternPool(keyPattern, new BigInteger(Math.Pow(2, settings.ChunkSize)));
54            StatisticsGenerator = new StatisticsGenerator(status, quickWatch, keySearcher, settings, this);
55            quickWatch.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(UpdateStatusContainerInQuickWatch));
56        }
57
58        public void Execute()
59        {
60            status.CurrentOperation = "Initializing connection to the peer-to-peer system";
61            new ConnectionHelper(keySearcher, settings).ValidateConnectionToPeerToPeerSystem();
62
63            if (!P2PManager.IsConnected)
64            {
65                keySearcher.GuiLogMessage("Unable to use peer-to-peer system.", NotificationLevel.Error);
66                status.CurrentOperation = "Unable to use peer-to-peer system";
67                return;
68            }
69
70            status.CurrentOperation = "Initializing distributed key pool tree";
71            keyPoolTree = new KeyPoolTree(patternPool, keySearcher, keyQualityHelper, keyGenerator, status, StatisticsGenerator);
72
73            keySearcher.GuiLogMessage(
74                "Total amount of patterns: " + patternPool.Length + ", each containing " + patternPool.PartSize +
75                " keys.", NotificationLevel.Info);
76            status.CurrentOperation = "Ready for calculation";
77
78            status.StartDate = keyPoolTree.StartDate();
79            //----------------------------------------------
80            status.JobSubmitterID = keyPoolTree.SubmitterID();
81            //-----------------------------------------------
82
83            keyPoolTree.UpdateStatusForNewCalculation();
84
85            Leaf currentLeaf;
86            while (!keySearcher.stop)
87            {
88                status.IsCurrentProgressIndeterminate = true;
89
90                BigInteger displayablePatternId;
91                try
92                {
93                    status.CurrentOperation = "Finding next leaf to calculate";
94                    currentLeaf = keyPoolTree.FindNextLeaf();
95                    if (currentLeaf == null)
96                    {
97                        break;
98                    }
99                    displayablePatternId = currentLeaf.PatternId() + 1;
100                }
101                catch (AlreadyCalculatedException)
102                {
103                    keySearcher.GuiLogMessage("Node was already calculated.", NotificationLevel.Info);
104                    keyPoolTree.Reset();
105                    continue;
106                }
107                catch (KeySearcherStopException)  //Fullstopfunction
108                {
109                    keySearcher.GuiLogMessage("Keysearcher Fullstop.", NotificationLevel.Error);
110                    keySearcher.GuiLogMessage("Please Update your Version.", NotificationLevel.Error);
111                    keySearcher.stop = true;
112                    return;
113                }
114
115                // TODO if reserve returns successfully, start timer to update our reserveration every few minutes
116                // if we cannot reacquire our lock in the timer, calculation must be aborted
117                if (!currentLeaf.ReserveLeaf())
118                {
119                    keySearcher.GuiLogMessage(
120                        "Pattern #" + displayablePatternId +
121                        " was reserved before it could be reserved for this CrypTool instance.",
122                        NotificationLevel.Info);
123                    keyPoolTree.Reset();
124                    continue;
125                }
126
127                var reservationTimer = new Timer {Interval = 5*60*1000};    //Every 5 minutes
128                reservationTimer.Elapsed += new ElapsedEventHandler(delegate
129                                                                        {
130                                                                            var oldMessage = status.CurrentOperation;
131                                                                            var message = string.Format("Rereserving pattern #{0}", displayablePatternId);
132                                                                            keySearcher.GuiLogMessage(message, NotificationLevel.Info);
133                                                                            status.CurrentOperation = message;
134                                                                            currentLeaf.ReserveLeaf();
135                                                                            status.CurrentOperation = oldMessage;
136                                                                        });
137
138                keySearcher.GuiLogMessage(
139                    "Running pattern #" + displayablePatternId + " of " + patternPool.Length,
140                    NotificationLevel.Info);
141                status.CurrentChunk = displayablePatternId;
142                status.CurrentOperation = "Calculating pattern " + status.CurrentChunk;
143
144                try
145                {
146                    LinkedList<KeySearcher.ValueKey> result;
147
148                    status.IsCurrentProgressIndeterminate = false;
149                    StopWatch.Start();
150                    reservationTimer.Start();
151                    try
152                    {
153                        result = keySearcher.BruteForceWithLocalSystem(patternPool[currentLeaf.PatternId()], true);
154                    }
155                    finally
156                    {
157                        reservationTimer.Stop();
158                        reservationTimer.Dispose();
159                        StopWatch.Stop();
160                        status.IsCurrentProgressIndeterminate = true;
161                    }
162
163                    if (!keySearcher.stop)
164                    {
165                        status.CurrentOperation = "Processing results of calculation";
166                        KeyPoolTree.ProcessCurrentPatternCalculationResult(currentLeaf, result);
167                        StatisticsGenerator.ProcessPatternResults(result);
168
169                        status.CurrentOperation = "Calculating global statistics";
170                        StatisticsGenerator.CalculateGlobalStatistics(displayablePatternId);
171
172                        status.LocalFinishedChunks++;
173                        keySearcher.GuiLogMessage(
174                            string.Format("Best match: {0} with {1}", result.First.Value.key, result.First.Value.value),
175                            NotificationLevel.Info);
176
177                        status.CurrentOperation = "Updating status in DHT";
178                        keyPoolTree.UpdateStatus(currentLeaf);
179                    }
180                    else
181                    {
182                        keySearcher.GuiLogMessage("Brute force was stopped, not saving results...",
183                                                  NotificationLevel.Info);
184                        status.ProgressOfCurrentChunk = 0;
185                        currentLeaf.GiveLeafFree();
186                        var message = string.Format("Removed reservation of pattern #{0}", displayablePatternId);
187                        keySearcher.GuiLogMessage(message, NotificationLevel.Info);
188                        status.CurrentOperation = message;
189                    }
190                }
191                catch (ReservationRemovedException)
192                {
193                    keySearcher.GuiLogMessage("Reservation removed by another node (while calculating). " +
194                                              "To avoid a state in limbo, proceeding to first available leaf...",
195                                              NotificationLevel.Info);
196                    keyPoolTree.Reset();
197                    continue;
198                }
199                catch (UpdateFailedException e)
200                {
201                    keySearcher.GuiLogMessage("Could not store results: " + e.Message, NotificationLevel.Info);
202                    keyPoolTree.Reset();
203                    continue;
204                }
205
206                // Push statistics to database
207                status.CurrentOperation = "Pushing statistics to evaluation database";
208                DatabaseStatistics.PushToDatabase(status, StopWatch.ElapsedMilliseconds, keyPoolTree.Identifier, settings, keySearcher);
209            }
210
211            // Set progress to 100%
212            if (!keySearcher.stop && keyPoolTree.IsCalculationFinished())
213            {
214                keySearcher.showProgress(keySearcher.costList, 1, 1, 1);
215                keySearcher.GuiLogMessage("Calculation complete.", NotificationLevel.Info);
216                keyPoolTree.UpdateStatusForFinishedCalculation();
217            }
218
219            StatisticsGenerator.CalculationStopped();
220            status.ProgressOfCurrentChunk = 0;
221            status.IsSearchingForReservedNodes = false;
222            status.IsCurrentProgressIndeterminate = false;
223            status.CurrentOperation = "Idle";
224            status.RemainingTimeTotal = new TimeSpan(0);
225        }
226
227        private void UpdateStatusContainerInQuickWatch()
228        {
229            quickWatch.DataContext = status;
230            quickWatch.UpdateSettings(keySearcher, settings);
231        }
232    }
233}
Note: See TracBrowser for help on using the repository browser.