source: trunk/CrypPlugins/QuadraticSieve/QuadraticSieve.cs @ 1678

Last change on this file since 1678 was 1678, checked in by Sven Rech, 12 years ago

quadratic sieve changes

File size: 35.1 KB
Line 
1/*                             
2   Copyright 2009 Team CrypTool (Sven Rech,Dennis Nolte,Raoul Falk,Nils Kopal), Uni Duisburg-Essen
3
4   Licensed under the Apache License, Version 2.0 (the "License");
5   you may not use this file except in compliance with the License.
6   You may obtain a copy of the License at
7
8       http://www.apache.org/licenses/LICENSE-2.0
9
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15*/
16
17using System;
18using System.Collections;
19using System.Linq;
20using System.Text;
21using Cryptool.PluginBase;
22using Cryptool.PluginBase.IO;
23using Cryptool.PluginBase.Miscellaneous;
24using System.ComponentModel;
25using System.Threading;
26using System.IO;
27using System.Windows.Controls;
28using System.Windows.Threading;
29using System.Windows;
30using System.Reflection;
31using System.Numerics;
32using System.Collections.Generic;
33using System.Diagnostics;
34using Cryptool.P2P;
35
36namespace Cryptool.Plugins.QuadraticSieve
37{
38    /// <summary>
39    /// This class wraps the msieve algorithm in version 1.42 which you can find at http://www.boo.net/~jasonp/qs.html
40    /// It also extends the msieve functionality to multi threading
41    /// Many thanks to the author of msieve "jasonp_sf"
42    ///
43    /// For further information on quadratic sieve or msieve please have a look at the above mentioned URL
44    /// </summary>
45    [Author("Sven Rech", "rech@cryptool.org", "Uni Duisburg-Essen", "http://www.uni-due.de")]
46    [PluginInfo(false, "Quadratic Sieve", "Sieving Primes", "QuadraticSieve/DetailedDescription/Description.xaml", "QuadraticSieve/iconqs.png")]
47    class QuadraticSieve : DependencyObject, IThroughput
48    {
49        #region private variables
50
51        private readonly string directoryName;
52        private QuadraticSieveSettings settings;
53        private BigInteger inputNumber;
54        private BigInteger[] outputFactors;
55        private bool running;
56        private Queue yieldqueue;
57        private AutoResetEvent yieldEvent = new AutoResetEvent(false);
58        private IntPtr obj = IntPtr.Zero;
59        private volatile int threadcount = 0;
60        private ArrayList conf_list;
61        private Mutex conf_listMutex = new Mutex();
62        private bool userStopped = false;
63        private FactorManager factorManager;
64        private PeerToPeer peerToPeer;
65        private bool usePeer2Peer;
66        private bool useGnuplot = false;
67        private StreamWriter gnuplotFile;
68        private double[] relationsPerMS;
69
70        private static Assembly msieveDLL = null;
71        private static Type msieve = null;
72        private static bool alreadyInUse = false;
73        private static Mutex alreadyInUseMutex = new Mutex();
74
75        #endregion
76
77        #region events
78
79        public event StatusChangedEventHandler OnPluginStatusChanged;
80        public event GuiLogNotificationEventHandler OnGuiLogNotificationOccured;
81        public event PluginProgressChangedEventHandler OnPluginProgressChanged;
82        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
83        public event PluginProgressChangedEventHandler OnPluginProcessChanged;
84
85        #endregion
86
87        #region public
88
89        /// <summary>
90        /// Constructor
91        ///
92        /// constructs a new QuadraticSieve plugin
93        /// </summary>
94        public QuadraticSieve()
95        {
96            Settings = new QuadraticSieveSettings();
97
98            directoryName = Path.Combine(DirectoryHelper.DirectoryLocalTemp, "msieve");
99            if (!Directory.Exists(directoryName)) Directory.CreateDirectory(directoryName);
100
101            QuickWatchPresentation = new QuadraticSievePresentation();
102
103            peerToPeer = new PeerToPeer(quadraticSieveQuickWatchPresentation, yieldEvent);
104            peerToPeer.P2PWarning += new PeerToPeer.P2PWarningHandler(peerToPeer_P2PWarning);
105           
106            quadraticSieveQuickWatchPresentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
107            {
108                quadraticSieveQuickWatchPresentation.peer2peer.Visibility = settings.UsePeer2Peer ? Visibility.Visible : Visibility.Collapsed;               
109                quadraticSieveQuickWatchPresentation.timeLeft.Text = "?";
110                quadraticSieveQuickWatchPresentation.endTime.Text = "?";
111                quadraticSieveQuickWatchPresentation.logging.Text = "Currently not sieving.";
112            }
113            , null);
114        }
115
116        /// <summary>
117        /// Getter / Setter for the settings of this plugin
118        /// </summary>
119        public Cryptool.PluginBase.ISettings Settings
120        {
121            get { return this.settings; }
122            set
123            {
124                this.settings = (QuadraticSieveSettings)value;
125                this.settings.PropertyChanged += new PropertyChangedEventHandler(settings_PropertyChanged);
126            }
127        }
128
129        private void settings_PropertyChanged(object sender, PropertyChangedEventArgs e)
130        {
131            if (e.PropertyName == "UsePeer2Peer")
132            {
133                if (quadraticSieveQuickWatchPresentation != null)
134                {
135                    quadraticSieveQuickWatchPresentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
136                    {
137                        quadraticSieveQuickWatchPresentation.peer2peer.Visibility = settings.UsePeer2Peer ? Visibility.Visible : Visibility.Collapsed;                       
138                    }, null);
139                }
140            }
141        }
142
143        /// <summary>
144        /// Called by the environment before executing this plugin
145        /// </summary>
146        public void PreExecution()
147        { 
148        }
149       
150        /// <summary>
151        /// Called by the environment to execute this plugin
152        /// </summary>
153        public void Execute()
154        {
155            if (checkInUse())
156                return;
157            try
158            {
159                usePeer2Peer = settings.UsePeer2Peer;
160                if (usePeer2Peer && !P2PManager.IsConnected)
161                {
162                    GuiLogMessage("No connection to Peer2Peer network. Sieving locally now!", NotificationLevel.Warning);
163                    usePeer2Peer = false;
164                }
165                if (usePeer2Peer && settings.Channel.Trim() == "")
166                {
167                    GuiLogMessage("No channel for Peer2Peer network specified. Sieving locally now!", NotificationLevel.Warning);
168                    usePeer2Peer = false;
169                }
170                if (usePeer2Peer)
171                {
172                    peerToPeer.SetChannel(settings.Channel);
173                    peerToPeer.SetNumber(InputNumber);
174                }
175
176                if (useGnuplot)
177                    gnuplotFile = new StreamWriter(Path.Combine(directoryName, "gnuplot.dat"), false);
178
179                userStopped = false;
180
181                if (InputNumber != 0)
182                {
183                    if (InputNumber.ToString().Length >= 275)
184                    {
185                        GuiLogMessage("Input too big.", NotificationLevel.Error);
186                        return;
187                    }
188
189                    String timeLeft_message = "?";
190                    String endtime_message = "?";
191                    String logging_message = "Starting quadratic sieve, please wait!";
192
193                    GuiLogMessage(logging_message, NotificationLevel.Info);
194                    quadraticSieveQuickWatchPresentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
195                    {
196                        quadraticSieveQuickWatchPresentation.ProgressYields.Clear();
197                        quadraticSieveQuickWatchPresentation.logging.Text = logging_message;
198                        quadraticSieveQuickWatchPresentation.endTime.Text = endtime_message;
199                        quadraticSieveQuickWatchPresentation.timeLeft.Text = timeLeft_message;
200                        quadraticSieveQuickWatchPresentation.factorList.Items.Clear();
201                        quadraticSieveQuickWatchPresentation.factorInfo.Content = "Searching trivial factors!";
202                        if (usePeer2Peer)
203                            quadraticSieveQuickWatchPresentation.relationsInfo.Content = "";
204                        else
205                            quadraticSieveQuickWatchPresentation.relationsInfo.Content = "Only local sieving!";
206                    }
207                    , null);
208
209                    DateTime start_time = DateTime.Now;
210
211                    initMsieveDLL();
212                    factorManager = new FactorManager(msieve.GetMethod("getPrimeFactors"), msieve.GetMethod("getCompositeFactors"), InputNumber);
213                    factorManager.FactorsChanged += this.FactorsChanged;
214
215                    //Now factorize:               
216                    try
217                    {
218                        string file = Path.Combine(directoryName, "" + InputNumber + ".dat");
219                        if (settings.DeleteCache && File.Exists(file))
220                            File.Delete(file);
221                        MethodInfo start = msieve.GetMethod("start");
222                        start.Invoke(null, new object[] { InputNumber.ToString(), file });
223                        obj = IntPtr.Zero;
224                    }
225                    catch (Exception ex)
226                    {
227                        GuiLogMessage("Error using msieve. " + ex.Message, NotificationLevel.Error);
228                        stopThreads();
229                        return;
230                    }
231
232                    if (!userStopped)
233                    {
234                        timeLeft_message = "0 seconds left";
235                        endtime_message = "" + (DateTime.Now);
236                        logging_message = "Sieving finished in " + (DateTime.Now - start_time) + "!";
237
238                        GuiLogMessage(logging_message, NotificationLevel.Info);
239                        quadraticSieveQuickWatchPresentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
240                        {
241                            quadraticSieveQuickWatchPresentation.logging.Text = logging_message;
242                            quadraticSieveQuickWatchPresentation.endTime.Text = endtime_message;
243                            quadraticSieveQuickWatchPresentation.timeLeft.Text = timeLeft_message;
244                            quadraticSieveQuickWatchPresentation.factorInfo.Content = "";
245                        }
246                        , null);
247
248                        Debug.Assert(factorManager.CalculateNumber() == InputNumber);
249                        OutputFactors = factorManager.getPrimeFactors();
250                    }
251                    else
252                    {
253                        timeLeft_message = "0 sec left";
254                        endtime_message = "Stopped";
255                        logging_message = "Stopped by user!";
256
257                        GuiLogMessage(logging_message, NotificationLevel.Info);
258                        quadraticSieveQuickWatchPresentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
259                        {
260                            quadraticSieveQuickWatchPresentation.logging.Text = logging_message;
261                            quadraticSieveQuickWatchPresentation.endTime.Text = endtime_message;
262                            quadraticSieveQuickWatchPresentation.timeLeft.Text = timeLeft_message;
263                            quadraticSieveQuickWatchPresentation.factorInfo.Content = "";
264                        }
265                        , null);
266                    }
267
268                    ProgressChanged(1, 1);
269
270                }
271                if (useGnuplot)
272                    gnuplotFile.Close();
273            }
274            finally
275            {
276                alreadyInUse = false;
277            }
278        }
279
280        private bool checkInUse()
281        {
282            try
283            {
284                alreadyInUseMutex.WaitOne();
285                if (alreadyInUse)
286                {
287                    GuiLogMessage("QuadraticSieve plugin is only allowed to execute ones at a time due to technical restrictions.", NotificationLevel.Error);
288                    return true;
289                }
290                else
291                {
292                    alreadyInUse = true;
293                    return false;
294                }
295            }
296            finally
297            {
298                alreadyInUseMutex.ReleaseMutex();
299            }
300        }
301       
302        /// <summary>
303        /// Called by the environment after execution
304        /// </summary>
305        public void PostExecution()
306        {
307        }
308
309        /// <summary>
310        /// Called by the environment to pause execution
311        /// </summary>
312        public void Pause()
313        {
314        }
315
316        /// <summary>
317        /// Called by the environment to stop execution
318        /// </summary>
319        public void Stop()
320        {
321            this.userStopped = true;
322            if (obj != IntPtr.Zero)
323            {
324                stopThreads();
325                MethodInfo stop = msieve.GetMethod("stop");
326                stop.Invoke(null, new object[] { obj });
327            }
328
329        }
330
331        /// <summary>
332        /// Called by the environment to initialize this plugin
333        /// </summary>
334        public void Initialize()
335        {
336            settings.Initialize();
337        }
338
339        /// <summary>
340        /// Called by the environment to dispose this plugin
341        /// </summary>
342        public void Dispose()
343        {
344        }
345
346        /// <summary>
347        /// Getter / Setter for the input number which should be factorized
348        /// </summary>
349        [PropertyInfo(Direction.InputData, "Number input", "Enter the number you want to factorize", "", DisplayLevel.Beginner)]
350        public BigInteger InputNumber
351        {
352            get
353            {
354                return inputNumber;
355            }
356            set
357            {
358                this.inputNumber = value;
359                OnPropertyChanged("InputNumber");
360            }
361        }
362
363        /// <summary>
364        /// Getter / Setter for the factors calculated by msieve
365        /// </summary>
366        [PropertyInfo(Direction.OutputData, "Factors output", "Your factors will be sent here", "", DisplayLevel.Beginner)]
367        public BigInteger[] OutputFactors
368        {
369            get
370            {
371                return outputFactors;
372            }
373            set
374            {
375                this.outputFactors = value;
376                OnPropertyChanged("OutputFactors");
377            }
378        }
379       
380        /// <summary>
381        /// Called when a property of this plugin changes
382        /// </summary>
383        /// <param name="name">name</param>
384        public void OnPropertyChanged(string name)
385        {
386            EventsHelper.PropertyChanged(PropertyChanged, this, new PropertyChangedEventArgs(name));
387        }
388
389        /// <summary>
390        /// Getter / Setter for the presentation of this plugin
391        /// </summary>
392        public UserControl Presentation { get; private set; }
393
394        /// <summary>
395        /// Getter / Setter for the QuickWatchPresentation of this plugin
396        /// </summary>
397        public UserControl QuickWatchPresentation
398        {
399            get;
400            private set;
401        }
402
403        #endregion
404
405        #region private
406
407        /// <summary>
408        /// calculate a String which shows the timespan
409        ///
410        /// example
411        ///
412        ///     4 days
413        /// or
414        ///     2 minutes
415        /// </summary>
416        /// <param name="ts"></param>
417        /// <returns></returns>
418        private String showTimeSpan(TimeSpan ts)
419        {
420            String res = "";
421            if (ts.Days != 0)
422                res = ts.Days + " days ";
423            if (ts.Hours != 0 || res.Length != 0)
424                res += ts.Hours + " hours ";
425            if (ts.Minutes != 0)
426                res += ts.Minutes + " minutes";
427            if (res.Length == 0)
428                res += ts.Seconds + " seconds";
429            return res;
430        }
431
432        /// <summary>
433        /// Callback method to prepare sieving
434        /// Called by msieve
435        ///
436        /// </summary>
437        /// <param name="conf">pointer to configuration</param>
438        /// <param name="update">number of relations found</param>
439        /// <param name="core_sieve_fcn">pointer to internal sieve function of msieve</param>
440        private void prepareSieving(IntPtr conf, int update, IntPtr core_sieve_fcn, int max_relations)
441        {
442            int threads = Math.Min(settings.CoresUsed, Environment.ProcessorCount-1);
443            MethodInfo getObjFromConf = msieve.GetMethod("getObjFromConf");
444            this.obj = (IntPtr)getObjFromConf.Invoke(null, new object[] { conf });           
445            yieldqueue = Queue.Synchronized(new Queue());
446            conf_list = new ArrayList();
447
448            String message = "Start sieving using " + (threads + 1) + " cores!";
449            GuiLogMessage(message, NotificationLevel.Info);
450            quadraticSieveQuickWatchPresentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
451            {
452                quadraticSieveQuickWatchPresentation.logging.Text = message;
453                if (usePeer2Peer)
454                    quadraticSieveQuickWatchPresentation.relationsInfo.Content = "";
455            }
456            , null);         
457
458            ProgressChanged(0.1, 1.0);
459
460            running = true;
461            //start helper threads:
462            relationsPerMS = new double[threads + 1];
463            for (int i = 0; i < threads+1; i++)
464            {
465                MethodInfo cloneSieveConf = msieve.GetMethod("cloneSieveConf");
466                IntPtr clone = (IntPtr)cloneSieveConf.Invoke(null, new object[] { conf });               
467                conf_list.Add(clone);
468                WaitCallback worker = new WaitCallback(MSieveJob);
469                ThreadPool.QueueUserWorkItem(worker, new object[] { clone, update, core_sieve_fcn, yieldqueue, i });
470            }
471
472            //manage the yields of the other threads:
473            manageYields(conf, max_relations);  //this method returns as soon as there are enough relations found
474            if (userStopped)
475                return;
476
477            //sieving is finished now, so give some informations and stop threads:
478            ProgressChanged(0.9, 1.0);
479            GuiLogMessage("Sieving finished", NotificationLevel.Info);
480            quadraticSieveQuickWatchPresentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
481            {
482                quadraticSieveQuickWatchPresentation.timeLeft.Text = "";
483                quadraticSieveQuickWatchPresentation.endTime.Text = "";
484                quadraticSieveQuickWatchPresentation.factorInfo.Content = "Found enough relations! Please wait...";
485            }, null);
486           
487            stopThreads();
488            if (yieldqueue != null)
489                yieldqueue.Clear();
490        }
491
492        /// <summary>
493        /// Manages the whole yields that are created during the sieving process by the other threads (and other peers).
494        /// Returns true, if enough relations have been found.
495        /// </summary>
496        private void manageYields(IntPtr conf, int max_relations)
497        {
498            MethodInfo serializeYield = msieve.GetMethod("serializeYield");
499            MethodInfo deserializeYield = msieve.GetMethod("deserializeYield");
500            MethodInfo getNumRelations = msieve.GetMethod("getNumRelations");
501            int num_relations = (int)getNumRelations.Invoke(null, new object[] { conf });
502            int start_relations = num_relations;
503            DateTime start_sieving_time = DateTime.Now;
504            MethodInfo saveYield = msieve.GetMethod("saveYield");
505
506            while (num_relations < max_relations)
507            {
508                ProgressChanged((double)num_relations / max_relations * 0.8 + 0.1, 1.0);
509               
510                yieldEvent.WaitOne();               //wait until queue is not empty
511                if (userStopped)
512                    return;
513
514                while (yieldqueue.Count != 0)       //get all the results from the helper threads, and store them
515                {
516                    IntPtr yield = (IntPtr)yieldqueue.Dequeue();                   
517
518                    if (usePeer2Peer)
519                    {
520                        byte[] serializedYield = (byte[])serializeYield.Invoke(null, new object[] { yield });
521                        peerToPeer.Put(serializedYield);
522                    }
523
524                    saveYield.Invoke(null, new object[] { conf, yield });
525                }
526
527                if (usePeer2Peer)
528                {
529                    Queue dhtqueue = peerToPeer.GetLoadedYieldsQueue();
530                    while (dhtqueue.Count != 0)       //get all the loaded results from the DHT, and store them
531                    {
532                        byte[] yield = (byte[])dhtqueue.Dequeue();
533                        IntPtr deserializedYield = (IntPtr)deserializeYield.Invoke(null, new object[] { yield });
534                        saveYield.Invoke(null, new object[] { conf, deserializedYield });
535                    }
536                }
537
538                num_relations = (int)getNumRelations.Invoke(null, new object[] { conf });
539                showProgressPresentation(max_relations, num_relations, start_relations, start_sieving_time);
540
541                if (usePeer2Peer && !peerToPeer.SyncFactorManager(factorManager))   //another peer already finished sieving
542                {
543                    throw new AlreadySievedException();
544                }
545            }           
546        }
547
548        private void showProgressPresentation(int max_relations, int num_relations, int start_relations, DateTime start_sieving_time)
549        {
550            String logging_message = "Found " + num_relations + " of " + max_relations + " relations!";
551            double msleft = 0;
552
553            //calculate global performance in relations per ms:
554            double globalPerformance = 0;
555            foreach (double r in relationsPerMS)
556                globalPerformance += r;
557            if (usePeer2Peer)
558                globalPerformance += peerToPeer.GetP2PPerformance();
559
560            //Calculate the total time assuming that we can sieve 1 minute with the same performance:
561            double relationsCalculatableIn1Minute = 1000 * 60 * 1 * globalPerformance;
562            if (relationsCalculatableIn1Minute <= max_relations)
563            {
564                double p = ApproximatedPolynom(relationsCalculatableIn1Minute / max_relations);
565                double estimatedTotalTime = 1000 * 60 * 1 / p;
566
567                //Calculate the elapsed time assuming that we sieved with the same performance the whole time:
568                p = ApproximatedPolynom((double)num_relations / max_relations);
569                double estimatedElapsedTime = estimatedTotalTime * p;
570
571                //Calculate time left:
572                msleft = estimatedTotalTime - estimatedElapsedTime;
573                /*GuiLogMessage("Total: " + new TimeSpan(0, 0, 0, 0, (int)estimatedTotalTime), NotificationLevel.Info);
574                GuiLogMessage("Elapsed: " + new TimeSpan(0, 0, 0, 0, (int)estimatedElapsedTime), NotificationLevel.Info);*/
575            }           
576           
577            String timeLeft_message = "very soon";
578            String endtime_message = "very soon";
579            if (msleft > 0 && !double.IsInfinity(msleft))
580            {
581                TimeSpan ts = new TimeSpan(0, 0, 0, 0, (int)msleft);
582                timeLeft_message = showTimeSpan(ts) + " left";
583                endtime_message = "" + DateTime.Now.AddMilliseconds((long)msleft);
584            }
585
586            quadraticSieveQuickWatchPresentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
587            {
588                quadraticSieveQuickWatchPresentation.logging.Text = logging_message;
589                quadraticSieveQuickWatchPresentation.timeLeft.Text = timeLeft_message;
590                quadraticSieveQuickWatchPresentation.endTime.Text = endtime_message;
591            }, null);
592
593            if (useGnuplot)
594            {
595                double percentage = (double)num_relations / max_relations;
596                double time = (DateTime.Now - start_sieving_time).TotalSeconds;
597                gnuplotFile.WriteLine("" + time + "\t\t" + percentage);
598            }
599        }
600
601        private static double ApproximatedPolynom(double x)
602        {
603            double a = -3.55504;
604            double b = 8.62296;
605            double c = -7.75103;
606            double d = 3.65871;
607            double progress = a * x * x * x * x + b * x * x * x + c * x * x + d * x;
608            return progress;
609        }
610
611        /// <summary>
612        /// This callback method is called by msieve. "list" is the trivial factor list (i.e. it consists of the factors that have been found without
613        /// using the quadratic sieve algorithm).
614        /// The method then factors all the factors that are still composite by using the quadratic sieve.
615        /// </summary>
616        private void getTrivialFactorlist(IntPtr list, IntPtr obj)
617        {
618            //add the trivial factors to the factor list:
619            factorManager.AddFactors(list);
620
621            if (usePeer2Peer)
622                peerToPeer.SyncFactorManager(factorManager);
623           
624            MethodInfo msieve_run_core = msieve.GetMethod("msieve_run_core");
625
626            //Now factorize as often as needed:
627            while (!factorManager.OnlyPrimes())
628            {
629                //get one composite factor, which we want to sieve now:
630                BigInteger compositeFactor = factorManager.GetCompositeFactor();
631                showFactorInformations(compositeFactor);
632                if (usePeer2Peer)
633                    peerToPeer.SetFactor(compositeFactor);
634
635                try
636                {
637                    //now start quadratic sieve on it:               
638                    IntPtr resultList = (IntPtr)msieve_run_core.Invoke(null, new object[2] { obj, compositeFactor.ToString() });
639                    if (userStopped)
640                        return;
641
642                    factorManager.ReplaceCompositeByFactors(compositeFactor, resultList);   //add the result list to factorManager
643
644                    if (usePeer2Peer)
645                        peerToPeer.SyncFactorManager(factorManager);
646                }
647                catch (AlreadySievedException)
648                {
649                    GuiLogMessage("Another peer already finished factorization of composite factor" + compositeFactor + ". Sieving next one...", NotificationLevel.Info);
650                }
651            }
652        }
653
654        private void showFactorInformations(BigInteger compositeFactor)
655        {
656            quadraticSieveQuickWatchPresentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
657            {
658                String compRep;
659                if (compositeFactor.ToString().Length < 6)
660                    compRep = compositeFactor.ToString();
661                else
662                    compRep = compositeFactor.ToString().Substring(0, 4) + "...";
663                quadraticSieveQuickWatchPresentation.factorInfo.Content = "Now sieving first composite factor! (" + compRep + ")";
664            }, null);
665        }
666
667        /// <summary>
668        /// Helper Thread for msieve, which sieves for relations:
669        /// </summary>
670        /// <param name="param">params</param>
671        private void MSieveJob(object param)
672        {
673            threadcount++;
674            object[] parameters = (object[])param;
675            IntPtr clone = (IntPtr)parameters[0];
676            int update = (int)parameters[1];
677            IntPtr core_sieve_fcn = (IntPtr)parameters[2];
678            Queue yieldqueue = (Queue)parameters[3];
679            int threadNR = (int)parameters[4];
680
681            try
682            {
683                MethodInfo collectRelations = msieve.GetMethod("collectRelations");
684                MethodInfo getYield = msieve.GetMethod("getYield");
685                MethodInfo getAmountOfRelationsInYield = msieve.GetMethod("getAmountOfRelationsInYield");
686
687                Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;
688
689                while (running)
690                {
691                    try
692                    {
693                        //Calculate the performance of this thread:
694                        DateTime beginning = DateTime.Now;
695                        collectRelations.Invoke(null, new object[] { clone, update, core_sieve_fcn });
696                        IntPtr yield = (IntPtr)getYield.Invoke(null, new object[] { clone });
697
698                        int amountOfFullRelations = (int)getAmountOfRelationsInYield.Invoke(null, new object[] { yield });
699                        relationsPerMS[threadNR] = amountOfFullRelations / (DateTime.Now - beginning).TotalMilliseconds;
700
701                        if (usePeer2Peer)
702                            peerToPeer.SetOurPerformance(relationsPerMS);
703
704                        yieldqueue.Enqueue(yield);
705                        yieldEvent.Set();
706                    }
707                    catch (Exception ex)
708                    {
709                        GuiLogMessage("Error using msieve." + ex.Message, NotificationLevel.Error);
710                        threadcount = 0;
711                        return;
712                    }
713                }
714
715                conf_listMutex.WaitOne();
716                if (conf_list != null)
717                    conf_list[threadNR] = null;
718                MethodInfo freeSieveConf = msieve.GetMethod("freeSieveConf");
719                freeSieveConf.Invoke(null, new object[] { clone });
720                conf_listMutex.ReleaseMutex();
721            }
722            finally
723            {
724                threadcount--;
725            }
726        }       
727
728        /// <summary>
729        /// Stop all running threads
730        /// </summary>
731        private void stopThreads()
732        {
733            if (conf_list != null)
734            {
735                running = false;               
736
737                MethodInfo stop = msieve.GetMethod("stop");
738                MethodInfo getObjFromConf = msieve.GetMethod("getObjFromConf");
739
740                conf_listMutex.WaitOne();
741                foreach (Object conf in conf_list)
742                    if (conf != null)
743                        stop.Invoke(null, new object[] { getObjFromConf.Invoke(null, new object[] { (IntPtr)conf }) });
744
745                conf_list = null;
746                conf_listMutex.ReleaseMutex();
747
748                if (usePeer2Peer)
749                    peerToPeer.StopLoadStoreThread();
750
751                GuiLogMessage("Waiting for threads to stop!", NotificationLevel.Debug);
752                while (threadcount > 0)
753                {
754                    Thread.Sleep(0);
755                }
756                GuiLogMessage("Threads stopped!", NotificationLevel.Debug);
757            }
758        }   
759
760        /// <summary>
761        /// Change the progress of this plugin
762        /// </summary>
763        /// <param name="value">value</param>
764        /// <param name="max">max</param>
765        private void ProgressChanged(double value, double max)
766        {
767            EventsHelper.ProgressChanged(OnPluginProgressChanged, this, new PluginProgressEventArgs(value, max));
768        }
769
770        private void FactorsChanged(List<BigInteger> primeFactors, List<BigInteger> compositeFactors)
771        {
772            quadraticSieveQuickWatchPresentation.Dispatcher.Invoke(DispatcherPriority.Normal, (SendOrPostCallback)delegate
773            {
774                quadraticSieveQuickWatchPresentation.factorList.Items.Clear();
775
776                foreach (BigInteger pf in primeFactors)         
777                    quadraticSieveQuickWatchPresentation.factorList.Items.Add("Prime Factor: " + pf.ToString());           
778
779                foreach (BigInteger cf in compositeFactors)
780                    quadraticSieveQuickWatchPresentation.factorList.Items.Add("Composite Factor: " + cf.ToString());
781            }, null);
782        }
783
784        /// <summary>
785        /// Logs a message to the CrypTool gui
786        /// </summary>
787        /// <param name="p">p</param>
788        /// <param name="notificationLevel">notificationLevel</param>
789        private void GuiLogMessage(string p, NotificationLevel notificationLevel)
790        {
791            EventsHelper.GuiLogMessage(OnGuiLogNotificationOccured, this, new GuiLogEventArgs(p, this, notificationLevel));
792        }
793
794        /// <summary>
795        /// Getter / Setter for the QuickWatchPresentation
796        /// </summary>
797        private QuadraticSievePresentation quadraticSieveQuickWatchPresentation
798        {
799            get { return QuickWatchPresentation as QuadraticSievePresentation; }
800        }
801
802        /// <summary>
803        /// dynamically loads the msieve dll file and sets the callbacks
804        /// </summary>
805        private void initMsieveDLL()
806        {
807            //Load msieve.dll (if necessary):
808            if (msieve == null || msieveDLL == null)
809            {
810                string s = Directory.GetCurrentDirectory();
811                string dllname;
812                if (IntPtr.Size == 4)
813                    dllname = "msieve.dll";
814                else
815                    dllname = "msieve64.dll";
816
817                msieveDLL = Assembly.LoadFile(Directory.GetCurrentDirectory() + "\\AppReferences\\"  + dllname);
818                msieve = msieveDLL.GetType("Msieve.msieve");
819            }
820
821            //init msieve with callbacks:
822            MethodInfo initMsieve = msieve.GetMethod("initMsieve");
823            Object callback_struct = Activator.CreateInstance(msieveDLL.GetType("Msieve.callback_struct"));           
824            FieldInfo prepareSievingField = msieveDLL.GetType("Msieve.callback_struct").GetField("prepareSieving");
825            FieldInfo getTrivialFactorlistField = msieveDLL.GetType("Msieve.callback_struct").GetField("getTrivialFactorlist");           
826            Delegate prepareSievingDel = MulticastDelegate.CreateDelegate(msieveDLL.GetType("Msieve.prepareSievingDelegate"), this, "prepareSieving");
827            Delegate getTrivialFactorlistDel = MulticastDelegate.CreateDelegate(msieveDLL.GetType("Msieve.getTrivialFactorlistDelegate"), this, "getTrivialFactorlist");           
828            prepareSievingField.SetValue(callback_struct, prepareSievingDel);
829            getTrivialFactorlistField.SetValue(callback_struct, getTrivialFactorlistDel);
830            initMsieve.Invoke(null, new object[1] { callback_struct });
831        }
832
833        private void peerToPeer_P2PWarning(string warning)
834        {
835            GuiLogMessage(warning, NotificationLevel.Warning);
836        }
837
838        #endregion
839
840    }
841}
Note: See TracBrowser for help on using the repository browser.