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

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

some additional keysearcher fixes

File size: 14.6 KB
RevLine 
[1634]1using System;
[2024]2using System.Collections.Generic;
[1682]3using System.Diagnostics;
[1643]4using System.Numerics;
[2115]5using System.Threading;
[1682]6using System.Windows.Threading;
[1707]7using Cryptool.P2P;
[2115]8using Cryptool.P2P.Internal;
[1634]9using Cryptool.PluginBase;
10using KeySearcher.Helper;
[1674]11using KeySearcher.KeyPattern;
[1647]12using KeySearcher.P2P.Exceptions;
[1707]13using KeySearcher.P2P.Helper;
[1682]14using KeySearcher.P2P.Presentation;
[1674]15using KeySearcher.P2P.Storage;
16using KeySearcher.P2P.Tree;
[1682]17using KeySearcherPresentation.Controls;
[2024]18using System.Timers;
[2115]19using Timer = System.Timers.Timer;
[1634]20
21namespace KeySearcher.P2P
22{
[1674]23    internal class DistributedBruteForceManager
[1634]24    {
[1674]25        private readonly StorageKeyGenerator keyGenerator;
26        private readonly KeySearcher keySearcher;
[1682]27        private readonly KeySearcherSettings settings;
[1707]28        private readonly KeyQualityHelper keyQualityHelper;
[1682]29        private readonly P2PQuickWatchPresentation quickWatch;
[1674]30        private readonly KeyPatternPool patternPool;
[1682]31        private readonly StatusContainer status;
32        internal readonly StatisticsGenerator StatisticsGenerator;
33        internal readonly Stopwatch StopWatch;
[1634]34
[1707]35        private KeyPoolTree keyPoolTree;
[2115]36        private AutoResetEvent systemJoinEvent = new AutoResetEvent(false);
[1707]37
[1674]38        public DistributedBruteForceManager(KeySearcher keySearcher, KeyPattern.KeyPattern keyPattern, KeySearcherSettings settings,
[1682]39                                            KeyQualityHelper keyQualityHelper, P2PQuickWatchPresentation quickWatch)
[1634]40        {
[1674]41            this.keySearcher = keySearcher;
[1682]42            this.settings = settings;
[1707]43            this.keyQualityHelper = keyQualityHelper;
[1682]44            this.quickWatch = quickWatch;
[1634]45
[1647]46            // TODO when setting is still default (21), it is only displayed as 21 - but the settings-instance contains 0 for that key!
[1634]47            if (settings.ChunkSize == 0)
48            {
[1647]49                settings.ChunkSize = 21;
[1634]50            }
51
[1698]52            StopWatch = new Stopwatch();
[2078]53            status = new StatusContainer(keySearcher);
[1698]54            status.IsCurrentProgressIndeterminate = true;
55
[1674]56            keyGenerator = new StorageKeyGenerator(keySearcher, settings);
57            patternPool = new KeyPatternPool(keyPattern, new BigInteger(Math.Pow(2, settings.ChunkSize)));
[1682]58            StatisticsGenerator = new StatisticsGenerator(status, quickWatch, keySearcher, settings, this);
59            quickWatch.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(UpdateStatusContainerInQuickWatch));
[1707]60        }
[1682]61
[1707]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);
[1727]70                status.CurrentOperation = "Unable to use peer-to-peer system";
[1707]71                return;
72            }
73
[1705]74            status.CurrentOperation = "Initializing distributed key pool tree";
[2142]75            try
76            {
77                keyPoolTree = new KeyPoolTree(patternPool, keySearcher, keyQualityHelper, keyGenerator, status, StatisticsGenerator);
78            }
79            catch (KeySearcherStopException)
80            {
81                status.CurrentOperation = "PLEASE UPDATE";
82                keySearcher.GuiLogMessage("Keysearcher Fullstop.Please Update your Version.", NotificationLevel.Error);
83                keySearcher.Stop();
84                throw new KeySearcherStopException();
85            }
86           
[1707]87
[1674]88            keySearcher.GuiLogMessage(
89                "Total amount of patterns: " + patternPool.Length + ", each containing " + patternPool.PartSize +
[1665]90                " keys.", NotificationLevel.Info);
[1705]91            status.CurrentOperation = "Ready for calculation";
[1634]92
[1705]93            status.StartDate = keyPoolTree.StartDate();
[2074]94            //----------------------------------------------
95            status.JobSubmitterID = keyPoolTree.SubmitterID();
96            //-----------------------------------------------
97
[1729]98            keyPoolTree.UpdateStatusForNewCalculation();
[1705]99
[1665]100            Leaf currentLeaf;
[1674]101            while (!keySearcher.stop)
[1634]102            {
[1698]103                status.IsCurrentProgressIndeterminate = true;
104
[1727]105                BigInteger displayablePatternId;
[1671]106                try
107                {
[1705]108                    status.CurrentOperation = "Finding next leaf to calculate";
[1674]109                    currentLeaf = keyPoolTree.FindNextLeaf();
[1671]110                    if (currentLeaf == null)
111                    {
112                        break;
113                    }
[1727]114                    displayablePatternId = currentLeaf.PatternId() + 1;
[1674]115                }
116                catch (AlreadyCalculatedException)
[1671]117                {
[1698]118                    keySearcher.GuiLogMessage("Node was already calculated.", NotificationLevel.Info);
[1674]119                    keyPoolTree.Reset();
[1671]120                    continue;
121                }
[2094]122                catch (KeySearcherStopException)  //Fullstopfunction
123                {
[2142]124                    keySearcher.GuiLogMessage("Keysearcher Fullstop.Please Update your Version.", NotificationLevel.Debug);
125                    keyPoolTree.Reset();
126                    keySearcher.Stop();
[2094]127                    return;
128                }
[1671]129
[2017]130                // TODO if reserve returns successfully, start timer to update our reserveration every few minutes
131                // if we cannot reacquire our lock in the timer, calculation must be aborted
[1665]132                if (!currentLeaf.ReserveLeaf())
133                {
[1674]134                    keySearcher.GuiLogMessage(
[1727]135                        "Pattern #" + displayablePatternId +
[1665]136                        " was reserved before it could be reserved for this CrypTool instance.",
[1698]137                        NotificationLevel.Info);
[1674]138                    keyPoolTree.Reset();
[1665]139                    continue;
140                }
141
[2115]142                bool reservationRemoved = false;
[2024]143                var reservationTimer = new Timer {Interval = 5*60*1000};    //Every 5 minutes
144                reservationTimer.Elapsed += new ElapsedEventHandler(delegate
145                                                                        {
[2040]146                                                                            var oldMessage = status.CurrentOperation;
[2038]147                                                                            var message = string.Format("Rereserving pattern #{0}", displayablePatternId);
148                                                                            keySearcher.GuiLogMessage(message, NotificationLevel.Info);
149                                                                            status.CurrentOperation = message;
[2115]150                                                                            try
151                                                                            {
[2122]152                                                                                currentLeaf.ReserveLeaf();
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                                                                                //}
[2115]160                                                                            }
161                                                                            catch (Cryptool.P2P.Internal.NotConnectedException)
162                                                                            {
163                                                                                keySearcher.GuiLogMessage("Rereserving pattern failed, because there is no connection!",
164                                                                                        NotificationLevel.Warning);
165                                                                                //TODO: Register OnSystemJoined event to rereserve pattern immediately after reconnect
166                                                                            }
[2040]167                                                                            status.CurrentOperation = oldMessage;
[2024]168                                                                        });
169
[1674]170                keySearcher.GuiLogMessage(
[1727]171                    "Running pattern #" + displayablePatternId + " of " + patternPool.Length,
[1634]172                    NotificationLevel.Info);
[1727]173                status.CurrentChunk = displayablePatternId;
[1705]174                status.CurrentOperation = "Calculating pattern " + status.CurrentChunk;
[1634]175
[1647]176                try
177                {
[2024]178                    LinkedList<KeySearcher.ValueKey> result;
179
[1682]180                    status.IsCurrentProgressIndeterminate = false;
181                    StopWatch.Start();
[2024]182                    reservationTimer.Start();
183                    try
184                    {
185                        result = keySearcher.BruteForceWithLocalSystem(patternPool[currentLeaf.PatternId()], true);
[2115]186                        if (reservationRemoved)
187                        {
188                            keySearcher.stop = false;
189                            throw new ReservationRemovedException("");
190                        }
[2024]191                    }
192                    finally
193                    {
194                        reservationTimer.Stop();
195                        reservationTimer.Dispose();
196                        StopWatch.Stop();
197                        status.IsCurrentProgressIndeterminate = true;
198                    }
[1634]199
[1674]200                    if (!keySearcher.stop)
[1682]201                    {
[2115]202                        if (!P2PManager.IsConnected)
203                        {
204                            status.CurrentOperation = "Connection lost! Waiting for reconnection to store the results!";
205                            keySearcher.GuiLogMessage(status.CurrentOperation, NotificationLevel.Info);
206                           
207                            P2PManager.P2PBase.OnSystemJoined += new P2PBase.SystemJoined(P2PBase_OnSystemJoined);
208                            systemJoinEvent.WaitOne();
209                        }
210
[1705]211                        status.CurrentOperation = "Processing results of calculation";
[1674]212                        KeyPoolTree.ProcessCurrentPatternCalculationResult(currentLeaf, result);
[1682]213                        StatisticsGenerator.ProcessPatternResults(result);
[1727]214
215                        status.CurrentOperation = "Calculating global statistics";
216                        StatisticsGenerator.CalculateGlobalStatistics(displayablePatternId);
217
[1682]218                        status.LocalFinishedChunks++;
219                        keySearcher.GuiLogMessage(
[1703]220                            string.Format("Best match: {0} with {1}", result.First.Value.key, result.First.Value.value),
221                            NotificationLevel.Info);
[1727]222
223                        status.CurrentOperation = "Updating status in DHT";
224                        keyPoolTree.UpdateStatus(currentLeaf);
[1682]225                    }
[1647]226                    else
[1682]227                    {
[1674]228                        keySearcher.GuiLogMessage("Brute force was stopped, not saving results...",
229                                                  NotificationLevel.Info);
[1682]230                        status.ProgressOfCurrentChunk = 0;
[2038]231                        currentLeaf.GiveLeafFree();
232                        var message = string.Format("Removed reservation of pattern #{0}", displayablePatternId);
233                        keySearcher.GuiLogMessage(message, NotificationLevel.Info);
234                        status.CurrentOperation = message;
[1682]235                    }
[1665]236                }
[1674]237                catch (ReservationRemovedException)
[1634]238                {
[1674]239                    keySearcher.GuiLogMessage("Reservation removed by another node (while calculating). " +
240                                              "To avoid a state in limbo, proceeding to first available leaf...",
[1698]241                                              NotificationLevel.Info);
[1674]242                    keyPoolTree.Reset();
[1647]243                    continue;
[1634]244                }
[1665]245                catch (UpdateFailedException e)
246                {
[1698]247                    keySearcher.GuiLogMessage("Could not store results: " + e.Message, NotificationLevel.Info);
[1674]248                    keyPoolTree.Reset();
[1665]249                    continue;
250                }
[2142]251                catch (KeySearcherStopException)  //Fullstopfunction
252                {
253                    keySearcher.GuiLogMessage("Keysearcher Fullstop.Please Update your Version.", NotificationLevel.Debug);
254                    keyPoolTree.Reset();
255                    keySearcher.Stop();
256                    return;
257                }
[1751]258
259                // Push statistics to database
260                status.CurrentOperation = "Pushing statistics to evaluation database";
261                DatabaseStatistics.PushToDatabase(status, StopWatch.ElapsedMilliseconds, keyPoolTree.Identifier, settings, keySearcher);
[1634]262            }
263
264            // Set progress to 100%
[1674]265            if (!keySearcher.stop && keyPoolTree.IsCalculationFinished())
[1634]266            {
[2150]267                keySearcher.showProgress(keySearcher.costList, 1, 1, 1);
[1674]268                keySearcher.GuiLogMessage("Calculation complete.", NotificationLevel.Info);
[1727]269                keyPoolTree.UpdateStatusForFinishedCalculation();
[1634]270            }
[1698]271
[1708]272            StatisticsGenerator.CalculationStopped();
[1698]273            status.ProgressOfCurrentChunk = 0;
274            status.IsSearchingForReservedNodes = false;
275            status.IsCurrentProgressIndeterminate = false;
[1705]276            status.CurrentOperation = "Idle";
[1707]277            status.RemainingTimeTotal = new TimeSpan(0);
[1634]278        }
[1682]279
[2115]280        void P2PBase_OnSystemJoined()
281        {
282            P2PManager.P2PBase.OnSystemJoined -= P2PBase_OnSystemJoined;
283            systemJoinEvent.Set();
284        }
285
[1682]286        private void UpdateStatusContainerInQuickWatch()
287        {
288            quickWatch.DataContext = status;
289            quickWatch.UpdateSettings(keySearcher, settings);
290        }
[1634]291    }
[1674]292}
Note: See TracBrowser for help on using the repository browser.