source: trunk/CrypPlugins/KeyPatternJob/DistributableKeyPatternJob.cs @ 1448

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

replaced all BigInteger stuff with the new BigInteger class from .net 4.0

But there are still problems with some plugins (Keysearcher, BigInteger Operations...)

File size: 10.5 KB
Line 
1/* Copyright 2010 Team CrypTool (Christian Arnold), Uni Duisburg-Essen
2
3   Licensed under the Apache License, Version 2.0 (the "License");
4   you may not use this file except in compliance with the License.
5   You may obtain a copy of the License at
6
7       http://www.apache.org/licenses/LICENSE-2.0
8
9   Unless required by applicable law or agreed to in writing, software
10   distributed under the License is distributed on an "AS IS" BASIS,
11   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   See the License for the specific language governing permissions and
13   limitations under the License.
14*/
15
16using System;
17using System.Collections.Generic;
18using System.Linq;
19using System.Text;
20using KeySearcher;
21using Cryptool.PluginBase.Miscellaneous;
22using System.Numerics;
23
24namespace Cryptool.Plugins.PeerToPeer.Jobs
25{
26    public class DistributableKeyPatternJob : IDistributableJob
27    {
28        public event LastJobAllocated OnLastJobAllocated;
29        public event LastResultReceived OnLastResultReceived;
30
31        #region Variables and Properties
32
33        byte[] encryptData;
34        public byte[] EncryptData
35        {
36            get { return this.encryptData ; }
37            set { this.encryptData = value; }
38        }
39
40        byte[] initVector;
41        public byte[] InitVector
42        { 
43            get { return this.initVector; }
44            set { this.initVector = value; }
45        }
46
47        /// <summary>
48        /// increment this counter every time you produce a NEW job. When you pop a
49        /// already created Job from the pattern Buffer, don't increment this value.
50        /// Use the JobId existing in the KeyPatternJobPart-Element.
51        /// </summary>
52        BigInteger jobIdCounter = 0;
53        /// <summary>
54        /// main pattern stack
55        /// </summary>
56        KeyPatternPool patternPool;
57
58        /// <summary>
59        /// buffer for patterns which were popped from the patternPool, but were declined by the worker
60        /// </summary>
61        Stack<KeyPatternJobPart> patternBuffer;
62        /// <summary>
63        /// when a new Pattern will be requested, it will be copied
64        /// in this list. When a JobAccepted message arrived, move this
65        /// entry to the processingPatterns Dictionary. When a JobDeclined
66        /// Message arrived, remove the pattern from this Dictionary and
67        /// add the Job to the patternBuffer.
68        /// </summary>
69        Dictionary<BigInteger, KeyPatternJobPart> allocatedPatterns;
70        /// <summary>
71        /// Not before receiving the JobAccepted message from the worker,
72        /// the allocatedPattern entry will be moved to this list
73        /// </summary>
74        Dictionary<BigInteger, KeyPatternJobPart> patternsInProgress;
75        Dictionary<BigInteger, KeyPatternJobResult> finishedPatterns;
76
77        private LinkedList<KeySearcher.KeySearcher.ValueKey> globalResultList;
78        public LinkedList<KeySearcher.KeySearcher.ValueKey> GlobalResultList
79        {
80            get { return this.globalResultList;}
81            private set { this.globalResultList = value; }
82        }
83
84        public BigInteger TotalAmount
85        {
86            get { return this.patternPool.Count() + this.patternBuffer.Count + this.patternsInProgress.Count + this.allocatedPatterns.Count + this.finishedPatterns.Count; }
87            set { throw new NotImplementedException(); }
88        }
89
90        public BigInteger AllocatedAmount
91        {
92            get { return this.allocatedPatterns.Count + this.patternsInProgress.Count; }
93            set { throw new NotImplementedException(); }
94        }
95
96        public BigInteger FinishedAmount
97        {
98            get { return this.finishedPatterns.Count; }
99            set { throw new NotImplementedException(); }
100        }
101
102        #endregion
103
104        public DistributableKeyPatternJob(KeyPattern pattern, BigInteger partSize, byte[] encryptData, byte[] initVector)
105        {
106            this.EncryptData = encryptData;
107            this.InitVector = initVector;
108
109            this.patternPool = new KeyPatternPool(pattern, partSize);
110            this.patternBuffer = new Stack<KeyPatternJobPart>();
111            this.allocatedPatterns = new Dictionary<BigInteger, KeyPatternJobPart>();
112            this.patternsInProgress = new Dictionary<BigInteger, KeyPatternJobPart>();
113            this.finishedPatterns = new Dictionary<BigInteger, KeyPatternJobResult>();
114
115            this.GlobalResultList = new LinkedList<KeySearcher.KeySearcher.ValueKey>();
116        }
117
118        #region IDistributableJob Members
119
120        public byte[] Pop(out BigInteger jobId)
121        {
122            byte[] serializedJob = null;
123            jobId = -1;
124
125            if (this.patternBuffer.Count > 0)
126            {
127                KeyPatternJobPart jobPart = this.patternBuffer.Pop();
128                jobId = jobPart.JobId;
129                serializedJob = jobPart.Serialize();
130                this.allocatedPatterns.Add(jobId, jobPart);
131            }
132            else
133            {
134                KeyPattern poppedPattern = this.patternPool.Pop();
135                if (poppedPattern != null)
136                {
137                    // create a new JobPart element
138                    jobId = jobIdCounter++;
139                    KeyPatternJobPart jobPart = new KeyPatternJobPart(jobId, poppedPattern, this.EncryptData, this.InitVector);
140                    serializedJob = jobPart.Serialize();
141                    this.allocatedPatterns.Add(jobId, jobPart);
142
143                    if (this.patternPool.Count() == 0)
144                        if (OnLastJobAllocated != null)
145                            OnLastJobAllocated(jobId);
146                }
147            }
148            return serializedJob;
149        }
150
151        public void Push(BigInteger jobId)
152        {
153            if (this.allocatedPatterns.ContainsKey(jobId))
154            {
155                this.patternBuffer.Push(this.allocatedPatterns[jobId]);
156                //when a job is pushed on the "patternBuffer", this indicates, that worker leaves the network
157                this.allocatedPatterns.Remove(jobId);
158            }
159
160            if (this.patternsInProgress.ContainsKey(jobId))
161            {
162                this.patternBuffer.Push(this.patternsInProgress[jobId]);
163                //when a job is pushed on the "patternBuffer", this indicates, that worker leaves the network
164                this.patternsInProgress.Remove(jobId);
165            }
166        }
167
168        public double ProcessProgress()
169        {
170            throw new NotImplementedException();
171        }
172
173        public void JobAccepted(BigInteger jobId)
174        {
175            if (this.allocatedPatterns.ContainsKey(jobId))
176            {
177                this.patternsInProgress.Add(jobId, this.allocatedPatterns[jobId]);
178                this.allocatedPatterns.Remove(jobId);
179            }
180            //dirty workaround because P2PJobAdmin sends the accepted/declined msg twice...
181            //else
182            //    throw (new Exception("The job-accepted-message for jobId '"+ jobId.ToString() + "' isn't valid"));
183        }
184
185        public void JobDeclined(BigInteger jobId)
186        {
187            if (this.allocatedPatterns.ContainsKey(jobId))
188            {
189                this.patternBuffer.Push(this.allocatedPatterns[jobId]);
190                this.allocatedPatterns.Remove(jobId);
191            }
192            //dirty workaround because P2PJobAdmin sends the accepted/declined msg twice...
193            //else
194            //    throw (new Exception("The job-declined-message for jobId '" + jobId.ToString() + "' isn't valid"));
195        }
196
197        public TimeSpan SetResult(BigInteger jobId, byte[] result)
198        {
199            TimeSpan returnTimeSpan = new TimeSpan(0);
200            if (this.patternsInProgress.ContainsKey(jobId))
201            {
202                KeyPatternJobResult deserializedJobResult = new KeyPatternJobResult(result);
203               
204                MergeGlobalList(deserializedJobResult.Result);
205
206                returnTimeSpan = deserializedJobResult.ProcessingTime;
207                this.finishedPatterns.Add(jobId, deserializedJobResult);
208                this.patternsInProgress.Remove(jobId);
209            }
210            //dirty workaround because P2PJobAdmin sends the result msg twice...
211            //else
212            //    throw(new Exception("Received result from a job, which isn't in 'patternsInProgress' List."));
213            if (this.patternPool.Count() == 0 && this.patternsInProgress.Count == 0 && this.allocatedPatterns.Count == 0 && this.patternBuffer.Count == 0)
214            {
215                if (OnLastResultReceived != null)
216                    OnLastResultReceived(jobId);
217            }
218
219            return returnTimeSpan;
220        }
221
222        #endregion
223
224        #region Special Global Result List
225
226        private LinkedList<KeySearcher.KeySearcher.ValueKey> MergeGlobalList(LinkedList<KeySearcher.KeySearcher.ValueKey> listToCompare)
227        {
228            if (this.GlobalResultList.Count == 0)
229            {
230                this.GlobalResultList = listToCompare;
231                return this.GlobalResultList;
232            }
233
234            if (this.GlobalResultList.Last().value >= listToCompare.First().value)
235                return this.GlobalResultList;
236
237            LinkedListNode<KeySearcher.KeySearcher.ValueKey> globalNode = this.GlobalResultList.First;
238            LinkedListNode<KeySearcher.KeySearcher.ValueKey> temp_node = this.GlobalResultList.First;
239            LinkedListNode<KeySearcher.KeySearcher.ValueKey> localNode = listToCompare.First;
240
241            if (this.GlobalResultList.Count != listToCompare.Count)
242                throw (new Exception("The two lists, which you want to merge haven't the same length (GlobalList: " + this.GlobalResultList.Count + ", LocalList: " + listToCompare.Count));
243
244            while(localNode != null)
245            {
246                temp_node = globalNode;
247                while (globalNode != null)
248                {
249                    if (localNode.Value.value >= globalNode.Value.value)
250                    {
251                        this.GlobalResultList.AddBefore(globalNode, localNode.Value);
252                        this.GlobalResultList.RemoveLast();
253                        break;
254                    }
255                    globalNode = globalNode.Next;
256                }
257                globalNode = temp_node;
258                localNode = localNode.Next;
259            }
260
261            return this.GlobalResultList;
262        }
263
264        #endregion
265    }
266}
Note: See TracBrowser for help on using the repository browser.