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

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

Version 5
Added User-Information to KeyValues. (Fully Working)

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