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

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

Modified the bonus feature (Still testing)

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                            var a = binaryReader.BaseStream.Length;
171                            var b = binaryReader.BaseStream.Position;
172                            //reading the IDs and patterncount
173                            long maschID = binaryReader.ReadInt64();
174                            int count = binaryReader.ReadInt32();
175                            readMaschcount.Add(maschID, new Information(){Count = count, Hostname = "Unknown", Date = DateTime.MinValue});
176                        }
177                    }
178                    else
179                    {
180                        for (int j = 0; j < maschcount; j++)
181                        {
182                            //reading the IDs and patterncount
183                            long maschID = binaryReader.ReadInt64();
184                            int count = binaryReader.ReadInt32();
185                            string host = binaryReader.ReadString();
186                       
187                            var date = DateTime.FromBinary(binaryReader.ReadInt64());
188                            readMaschcount.Add(maschID, new Information() {Count = count, Hostname = host, Date = date});
189                        }
190                    }
191                    if (nodeToUpdate.Activity.ContainsKey(avatarname))
192                    {
193                        nodeToUpdate.Activity[avatarname] = readMaschcount;
194                    }
195                    else
196                    {
197                        nodeToUpdate.Activity.Add(avatarname, readMaschcount);                     
198                    }
199                }               
200            }
201                       
202            if (resultCount > 0)
203            {
204                keySearcher.IntegrateNewResults(nodeToUpdate.Result, nodeToUpdate.Activity, nodeToUpdate.DistributedJobIdentifier);
205                statisticsGenerator.ProcessPatternResults(nodeToUpdate.Result);
206            }
207
208            nodeToUpdate.UpdateCache();
209            return requestResult;
210        }
211
212        private static void UpdateNodeFromDht(Node nodeToUpdate, BinaryReader binaryReader)
213        {
214            nodeToUpdate.LeftChildFinished = binaryReader.ReadBoolean() || nodeToUpdate.LeftChildFinished;
215            nodeToUpdate.RightChildFinished = binaryReader.ReadBoolean() || nodeToUpdate.RightChildFinished;
216        }
217
218        private static void UpdateLeafFromDht(Leaf nodeToUpdate, BinaryReader binaryReader)
219        {
220            var oldVersionFlag = CheckVersion(binaryReader);
221               
222            var date = DateTime.FromBinary(binaryReader.ReadInt64());
223            if (date > nodeToUpdate.LastReservationDate)
224            {
225                nodeToUpdate.LastReservationDate = date;
226            }
227           
228            try
229            {
230                if (binaryReader.BaseStream.Length - binaryReader.BaseStream.Position >= 8)
231                {
232                    nodeToUpdate.setClientIdentifier(binaryReader.ReadInt64());
233                }
234                else
235                {
236                    throw new Exception();
237                }
238            }
239            catch (Exception)
240            {
241                // client id not available, use default
242                nodeToUpdate.setClientIdentifier(-1);
243            }
244           
245        }
246
247        internal static string KeyInDht(NodeBase node)
248        {
249            return string.Format("{0}_node_{1}_{2}", node.DistributedJobIdentifier, node.From, node.To);
250        }
251
252        private static int CheckVersion(BinaryReader binaryReader)
253        {           
254            try
255            {
256                //Checking if there's a version in the stream
257                int vers = binaryReader.PeekChar();
258                if (vers == 86)
259                {
260                    //Reading the char and the versionnumber
261                    char magic = binaryReader.ReadChar();
262                    int versionInUse = binaryReader.ReadInt32();
263                    //Check if a newer Version is in use
264                    if (versionInUse > version)
265                    {
266                        throw new KeySearcherStopException();
267                    }
268                    return versionInUse;
269                }
270                else
271                {
272                    return -1;
273                }
274            }
275            catch(KeySearcherStopException)
276            {
277                throw new KeySearcherStopException();
278            }
279           
280        }
281
282        public DateTime StartDate(String ofJobIdentifier)
283        {
284            var key = ofJobIdentifier + "_startdate";
285            var requestResult = RetrieveWithStatistic(key);
286
287            if (requestResult.IsSuccessful() && requestResult.Data != null)
288            {
289                var startTimeUtc = DateTime.SpecifyKind(
290                    DateTime.FromBinary(BitConverter.ToInt64(requestResult.Data, 0)), DateTimeKind.Utc);
291                return startTimeUtc.ToLocalTime();
292            }
293
294            StoreWithStatistic(key, BitConverter.GetBytes((DateTime.UtcNow.ToBinary())));
295            return DateTime.Now;
296        }
297
298        public long SubmitterID(String ofJobIdentifier)
299        {
300            var key = ofJobIdentifier + "_submitterid";
301            var requestResult = RetrieveWithStatistic(key);
302
303            if (requestResult.IsSuccessful() && requestResult.Data != null)
304            {
305                var submitterid = BitConverter.ToInt64(requestResult.Data, 0);
306                return submitterid;
307            }
308
309            StoreWithStatistic(key, BitConverter.GetBytes(Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetID()));
310            return Cryptool.PluginBase.Miscellaneous.UniqueIdentifier.GetID();
311        }
312
313        public RequestResult RetrieveWithStatistic(string key)
314        {
315            statusContainer.RetrieveRequests++;
316            statusContainer.TotalDhtRequests++;
317            var requestResult = P2PManager.Retrieve(key);
318
319            if (requestResult.Data != null)
320            {
321                statusContainer.RetrievedBytes += requestResult.Data.Length;
322                statusContainer.TotalBytes += requestResult.Data.Length;
323            }
324
325            return requestResult;
326        }
327
328        public RequestResult RemoveWithStatistic(string key)
329        {
330            statusContainer.RemoveRequests++;
331            statusContainer.TotalDhtRequests++;
332            return P2PManager.Remove(key);
333        }
334
335        public RequestResult StoreWithStatistic(string key, byte[] data)
336        {
337            statusContainer.StoreRequests++;
338            statusContainer.TotalDhtRequests++;
339            var requestResult = P2PManager.Store(key, data);
340
341            if (requestResult.Data != null)
342            {
343                statusContainer.StoredBytes += requestResult.Data.Length;
344                statusContainer.TotalBytes += requestResult.Data.Length;
345            }
346
347            return requestResult;
348        }
349    }
350}
Note: See TracBrowser for help on using the repository browser.