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

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

Versionnumber Start
(UPDATE)

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