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

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

Serialize of the User Statistics update (Writing+Reading in DHT available)
Still needs to be tested before usage!

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