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

Last change on this file since 1223 was 1223, checked in by arnold, 12 years ago

P2PManager: Invoke --> BeginInvoke for QuickWatchPresentation
DistributableKeyPatternJob: OnLastResultReceived-Event bug fixed

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