source: trunk/CrypPlugins/KeySearcher/P2P/Storage/StorageHelper.cs @ 2246

Last change on this file since 2246 was 2246, checked in by nolte, 11 years ago

Saving the MTC World Record Challenge (Test)

File size: 14.0 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.IO;
4using Cryptool.P2P;
5using Cryptool.P2P.Internal;
6using Cryptool.PluginBase;
7using KeySearcher.P2P.Exceptions;
8using KeySearcher.P2P.Presentation;
9using KeySearcher.P2P.Tree;
10
11namespace KeySearcher.P2P.Storage
12{
13    class StorageHelper
14    {
15        private readonly KeySearcher keySearcher;
16        private readonly StatisticsGenerator statisticsGenerator;
17        private readonly StatusContainer statusContainer;
18
19        //VERSIONNUMBER: Important. Set it +1 manually everytime the length of the MemoryStream Changes
20        private const int version = 3;
21        /*
22        -----------------------------Versionnumber Changelog---------------------------------------------
23        |   Version 1: Added the Versionnumber to the Stream
24        |   Version 2: Added the first User Statistics (Avatar,ID,Count) to the Stream
25        |   Version 3: Added version question (in front of results) + more statistic information (hostname,date) to the Stream
26        -------------------------------------------------------------------------------------------------
27         */
28
29        public StorageHelper(KeySearcher keySearcher, StatisticsGenerator statisticsGenerator, StatusContainer statusContainer)
30        {
31            this.keySearcher = keySearcher;
32            this.statisticsGenerator = statisticsGenerator;
33            this.statusContainer = statusContainer;
34        }
35
36        //-------------------------------------------------------------------------------------------
37        //AFTER CHANGING THE FOLLOWING METHODS INCREASE THE VERSION-NUMBER AT THE TOP OF THIS CLASS!
38        //-------------------------------------------------------------------------------------------
39        internal RequestResult UpdateInDht(NodeBase nodeToUpdate)
40        {
41            var memoryStream = new MemoryStream();
42            var binaryWriter = new BinaryWriter(memoryStream);
43
44            //TODO: Append Updater Version
45            binaryWriter.Write('V');
46            binaryWriter.Write(version); 
47
48            if (nodeToUpdate is Node)
49            {
50                UpdateNodeInDht((Node) nodeToUpdate, binaryWriter);
51            } else
52            {
53                UpdateLeafInDht((Leaf) nodeToUpdate, binaryWriter);
54            }
55
56            // Append results
57            binaryWriter.Write(nodeToUpdate.Result.Count);
58            foreach (var valueKey in nodeToUpdate.Result)
59            {
60                binaryWriter.Write(valueKey.key);
61                binaryWriter.Write(valueKey.value);
62                binaryWriter.Write(valueKey.decryption.Length);
63                binaryWriter.Write(valueKey.decryption);
64            }                       
65           
66 
67            //Creating a copy of the activity dictionary
68            var copyAct = nodeToUpdate.Activity;
69
70            //Write number of avatarnames
71            binaryWriter.Write(copyAct.Keys.Count);
72            foreach (string avatar in copyAct.Keys)
73            {
74                var maschCopy = copyAct[avatar];
75                //write avatarname
76                binaryWriter.Write(avatar);
77                //write the number of maschines for this avatar
78                binaryWriter.Write(maschCopy.Keys.Count);
79
80                foreach (long maschID in maschCopy.Keys)
81                {
82                    //write the maschines and their patterncount
83                    binaryWriter.Write(maschID);
84                    binaryWriter.Write(maschCopy[maschID].Count); //int 32
85                    binaryWriter.Write(maschCopy[maschID].Hostname); //String
86                    binaryWriter.Write(maschCopy[maschID].Date.ToBinary()); //DateTime
87                }
88            }
89
90            return StoreWithStatistic(KeyInDht(nodeToUpdate), memoryStream.ToArray());
91        }
92
93        private static void UpdateNodeInDht(Node nodeToUpdate, BinaryWriter binaryWriter)
94        {
95            binaryWriter.Write(nodeToUpdate.LeftChildFinished);
96            binaryWriter.Write(nodeToUpdate.RightChildFinished);
97        }
98
99        private static void UpdateLeafInDht(Leaf nodeToUpdate, BinaryWriter binaryWriter)
100        {
101            binaryWriter.Write('V');
102            binaryWriter.Write(version);
103            var buffer = nodeToUpdate.LastReservationDate.ToBinary();
104            binaryWriter.Write(buffer);
105            binaryWriter.Write(nodeToUpdate.getClientIdentifier());
106        }
107
108        internal RequestResult UpdateFromDht(NodeBase nodeToUpdate, bool forceUpdate = false)
109        {
110
111            if (!forceUpdate && nodeToUpdate.LastUpdate > DateTime.Now.Subtract(new TimeSpan(0, 0, 5)))
112            {
113                return new RequestResult { Status = RequestResultType.Success };
114            }
115
116            nodeToUpdate.LastUpdate = DateTime.Now;
117
118            var requestResult = RetrieveWithStatistic(KeyInDht(nodeToUpdate));
119            var nodeBytes = requestResult.Data;
120
121            if (nodeBytes == null)
122            {
123                return requestResult;
124            }
125
126            var binaryReader = new BinaryReader(new MemoryStream(nodeBytes));
127//---------------------------------------------------------------------------------------
128            //TODO: VersionCheck!
129            var oldVersionFlag = CheckVersion(binaryReader);
130//----------------------------------------------------------------------------------------
131            if (nodeToUpdate is Node)
132            {
133                UpdateNodeFromDht((Node) nodeToUpdate, binaryReader);
134            } else
135            {
136                UpdateLeafFromDht((Leaf)nodeToUpdate, binaryReader);
137            }
138
139            // Load results
140            var resultCount = binaryReader.ReadInt32();
141            for (var i = 0; i < resultCount; i++)
142            {
143                var newResult = new KeySearcher.ValueKey
144                                    {
145                                        key = binaryReader.ReadString(),
146                                        value = binaryReader.ReadDouble(),
147                                        decryption = binaryReader.ReadBytes(binaryReader.ReadInt32())
148                                    };
149                nodeToUpdate.Result.AddLast(newResult);
150            }
151           
152
153
154            if (binaryReader.BaseStream.Length != binaryReader.BaseStream.Position)
155            { 
156                //Reading the number of avatarnames
157                int avatarcount = binaryReader.ReadInt32();
158                for(int i=0; i<avatarcount;i++)
159                {
160                    //Reading the avatarname and the maschine-count for this name
161                    string avatarname = binaryReader.ReadString();
162                    int maschcount = binaryReader.ReadInt32();
163                    var readMaschcount = new Dictionary<long, Information>();
164                   
165                    //previous version 2 didn't had the Information
166                    if (oldVersionFlag < 3)
167                    {
168                        for (int j = 0; j < maschcount; j++)
169                        {
170                            //reading the IDs and patterncount
171                            long maschID = binaryReader.ReadInt64();
172                            int count = binaryReader.ReadInt32();
173                            if (maschID > 0)
174                            {
175                                readMaschcount.Add(maschID, new Information(){Count = count, Hostname = "Unknown", Date = DateTime.MinValue});
176                            }
177                        }
178                    }
179                    else
180                    {
181                        for (int j = 0; j < maschcount; j++)
182                        {
183                            //reading the IDs and patterncount
184                            long maschID = binaryReader.ReadInt64();
185                            int count = binaryReader.ReadInt32();
186                            string host = binaryReader.ReadString(); 
187                            var date = DateTime.FromBinary(binaryReader.ReadInt64());
188
189                            if (maschID > 0)
190                            {
191                                readMaschcount.Add(maschID, new Information() {Count = count, Hostname = host, Date = date});
192                            }
193                        }
194                    }
195                    if (nodeToUpdate.Activity.ContainsKey(avatarname))
196                    {
197                        nodeToUpdate.Activity[avatarname] = readMaschcount;
198                    }
199                    else
200                    {
201                        nodeToUpdate.Activity.Add(avatarname, readMaschcount);                     
202                    }
203                }               
204            }
205                       
206            if (resultCount > 0)
207            {
208                keySearcher.IntegrateNewResults(nodeToUpdate.Result, nodeToUpdate.Activity, nodeToUpdate.DistributedJobIdentifier);
209                statisticsGenerator.ProcessPatternResults(nodeToUpdate.Result);
210            }
211
212            nodeToUpdate.UpdateCache();
213            return requestResult;
214        }
215
216        private static void UpdateNodeFromDht(Node nodeToUpdate, BinaryReader binaryReader)
217        {
218            nodeToUpdate.LeftChildFinished = binaryReader.ReadBoolean() || nodeToUpdate.LeftChildFinished;
219            nodeToUpdate.RightChildFinished = binaryReader.ReadBoolean() || nodeToUpdate.RightChildFinished;
220        }
221
222        private static void UpdateLeafFromDht(Leaf nodeToUpdate, BinaryReader binaryReader)
223        {
224            var oldVersionFlag = CheckVersion(binaryReader);
225               
226            var date = DateTime.FromBinary(binaryReader.ReadInt64());
227            if (date > nodeToUpdate.LastReservationDate)
228            {
229                nodeToUpdate.LastReservationDate = date;
230            }
231           
232            try
233            {
234                if (binaryReader.BaseStream.Length - binaryReader.BaseStream.Position >= 8)
235                {
236                    nodeToUpdate.setClientIdentifier(binaryReader.ReadInt64());
237                }
238                else
239                {
240                    throw new Exception();
241                }
242            }
243            catch (Exception)
244            {
245                // client id not available, use default
246                nodeToUpdate.setClientIdentifier(-1);
247            }
248           
249        }
250
251        internal static string KeyInDht(NodeBase node)
252        {
253            return string.Format("{0}_node_{1}_{2}", node.DistributedJobIdentifier, node.From, node.To);
254        }
255
256        private static int CheckVersion(BinaryReader binaryReader)
257        {           
258            try
259            {
260                //Checking if there's a version in the stream
261                int vers = binaryReader.PeekChar();
262                if (vers == 86)
263                {
264                    //Reading the char and the versionnumber
265                    char magic = binaryReader.ReadChar();
266                    int versionInUse = binaryReader.ReadInt32();
267                    //Check if a newer Version is in use
268                    if (versionInUse > version)
269                    {
270                        throw new KeySearcherStopException();
271                    }
272                    return versionInUse;
273                }
274                else
275                {
276                    return -1;
277                }
278            }
279            catch(KeySearcherStopException)
280            {
281                throw new KeySearcherStopException();
282            }
283           
284        }
285
286        public DateTime StartDate(String ofJobIdentifier)
287        {
288            var key = ofJobIdentifier + "_startdate";
289            var requestResult = RetrieveWithStatistic(key);
290
291            if (requestResult.IsSuccessful() && requestResult.Data != null)
292            {
293                var startTimeUtc = DateTime.SpecifyKind(
294                    DateTime.FromBinary(BitConverter.ToInt64(requestResult.Data, 0)), DateTimeKind.Utc);
295                return startTimeUtc.ToLocalTime();
296            }
297
298            StoreWithStatistic(key, BitConverter.GetBytes((DateTime.UtcNow.ToBinary())));
299            return DateTime.Now;
300        }
301
302        public long SubmitterID(String ofJobIdentifier)
303        {
304            var key = ofJobIdentifier + "_submitterid";
305            var requestResult = RetrieveWithStatistic(key);
306
307            if (requestResult.IsSuccessful() && requestResult.Data != null)
308            {
309                var submitterid = BitConverter.ToInt64(requestResult.Data, 0);
310                return submitterid;
311            }
312
313            StoreWithStatistic(key, BitConverter.GetBytes(Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetID()));
314            return Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetID();
315        }
316
317        public RequestResult RetrieveWithStatistic(string key)
318        {
319            statusContainer.RetrieveRequests++;
320            statusContainer.TotalDhtRequests++;
321            var requestResult = P2PManager.Retrieve(key);
322
323            if (requestResult.Data != null)
324            {
325                statusContainer.RetrievedBytes += requestResult.Data.Length;
326                statusContainer.TotalBytes += requestResult.Data.Length;
327            }
328
329            return requestResult;
330        }
331
332        public RequestResult RemoveWithStatistic(string key)
333        {
334            statusContainer.RemoveRequests++;
335            statusContainer.TotalDhtRequests++;
336            return P2PManager.Remove(key);
337        }
338
339        public RequestResult StoreWithStatistic(string key, byte[] data)
340        {
341            statusContainer.StoreRequests++;
342            statusContainer.TotalDhtRequests++;
343            var requestResult = P2PManager.Store(key, data);
344
345            if (requestResult.Data != null)
346            {
347                statusContainer.StoredBytes += requestResult.Data.Length;
348                statusContainer.TotalBytes += requestResult.Data.Length;
349            }
350
351            return requestResult;
352        }
353    }
354}
Note: See TracBrowser for help on using the repository browser.