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

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

much better time approximation for quadratic sieve

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