~xibo-maintainers/xibo/halley

« back to all changes in this revision

Viewing changes to client/dotNET/FileCollector.cs

MergedĀ lp:~dangarner/xibo/105-client-filecorruption

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
using System.IO;
25
25
using System.Security.Cryptography;
26
26
using System.Xml;
 
27
using System.Diagnostics;
27
28
 
28
29
namespace XiboClient
29
30
{
30
31
    class FileCollector
31
32
    {
32
 
        public FileCollector(string xmlString)
 
33
        private CacheManager _cacheManager;
 
34
 
 
35
        public FileCollector(CacheManager cacheManager, string xmlString)
33
36
        {
 
37
            _cacheManager = cacheManager;
 
38
 
34
39
            xml = new XmlDocument();
35
40
 
36
41
            try
85
90
                    if (File.Exists(Properties.Settings.Default.LibraryPath + @"\" + path + ".xlf"))
86
91
                    {
87
92
                        // Read the current layout into a string
88
 
                        String md5sum = "";
89
 
                        try
90
 
                        {
91
 
                            StreamReader sr = new StreamReader(File.Open(Properties.Settings.Default.LibraryPath + @"\" + path + ".xlf", FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
92
 
 
93
 
                            md5sum = Hashes.MD5(sr.ReadToEnd() + "\n");
94
 
 
95
 
                            sr.Close();
96
 
                        }
97
 
                        catch (Exception ex)
98
 
                        {
99
 
                            System.Diagnostics.Debug.WriteLine(String.Format("Error opening {0} for MD5 check", Properties.Settings.Default.LibraryPath + @"\" + path + ".xlf"), "FileCollector - CompareAndCollect");
100
 
                            System.Diagnostics.Debug.WriteLine(ex.Message);
101
 
 
102
 
                            break;
103
 
                        }
 
93
                        String md5 = _cacheManager.GetMD5(path + ".xlf");
 
94
 
 
95
                        System.Diagnostics.Debug.WriteLine(String.Format("Comparing current MD5 [{0}] with given MD5 [{1}]", md5, attributes["md5"].Value));
104
96
 
105
97
                        // Now we have the md5, compare it to the md5 in the xml
106
 
                        if (attributes["md5"].Value != md5sum)
 
98
                        if (attributes["md5"].Value != md5)
107
99
                        {
108
100
                            // They are different 
109
101
                            // Get the file and save it
140
132
                    string path = attributes["path"].Value;
141
133
 
142
134
                    // Does this media exist?
143
 
                    if (!File.Exists(Properties.Settings.Default.LibraryPath + @"\" + path))
 
135
                    if (File.Exists(Properties.Settings.Default.LibraryPath + @"\" + path))
 
136
                    {
 
137
                        String md5 = _cacheManager.GetMD5(path);
 
138
 
 
139
                        System.Diagnostics.Debug.WriteLine(String.Format("Comparing current MD5 [{0}] with given MD5 [{1}]", md5, attributes["md5"].Value));
 
140
 
 
141
                        // MD5 the file to make sure it is the same.
 
142
                        if (md5 != attributes["md5"].Value)
 
143
                        {
 
144
                            // File changed
 
145
                            fileList.chunkOffset = 0;
 
146
                            fileList.chunkSize = 512000;
 
147
                            fileList.complete = false;
 
148
                            fileList.downloading = false;
 
149
                            fileList.path = path;
 
150
                            fileList.type = "media";
 
151
                            fileList.size = int.Parse(attributes["size"].Value);
 
152
                            fileList.md5 = attributes["md5"].Value;
 
153
                            fileList.retrys = 0;
 
154
 
 
155
                            files.Add(fileList);
 
156
                        }
 
157
                    }
 
158
                    else
144
159
                    {
145
160
                        // No - Get it (async call - with chunks... through another class?)
146
161
                        fileList.chunkOffset = 0;
192
207
            }
193
208
 
194
209
            // Start with the first file
195
 
            currentFile = 0;
 
210
            _currentFile = 0;
196
211
 
197
212
            // Preload the first filelist
198
 
            currentFileList = files[currentFile];
 
213
            _currentFileList = files[_currentFile];
199
214
 
200
215
            // Get the first file
201
216
            GetFile();
203
218
 
204
219
        void xmdsFile_GetFileCompleted(object sender, XiboClient.xmds.GetFileCompletedEventArgs e)
205
220
        {
206
 
            // Expect new schedule XML
207
 
            if (e.Error != null)
208
 
            {
209
 
                //There was an error - what do we do?
210
 
                // Log it
211
 
                System.Diagnostics.Debug.WriteLine(e.Error.Message, "WS Error");
212
 
 
213
 
                System.Diagnostics.Trace.WriteLine(String.Format("Error From WebService Get File. File=[{1}], Error=[{0}], Try No [{2}]", e.Error.Message, currentFileList.path, currentFileList.retrys));
214
 
 
215
 
                // Retry?
216
 
                if (currentFileList.retrys < 5)
217
 
                {
218
 
                    // Increment the Retrys
219
 
                    currentFileList.retrys++;
220
 
 
221
 
                    // Try again
222
 
                    GetFile();
223
 
                }
224
 
                else
225
 
                {
226
 
                    // Blacklist this file
227
 
                    string[] mediaPath = currentFileList.path.Split('.');
228
 
                    string mediaId = mediaPath[0];
229
 
 
230
 
                    BlackList blackList = new BlackList();
231
 
                    blackList.Add(currentFileList.path, BlackListType.All, String.Format("Max number of retrys failed. BlackListing for all displays. Error {0}", e.Error.Message));
232
 
 
233
 
                    // Move on
234
 
                    currentFile++;
235
 
                }
236
 
            }
237
 
            else
238
 
            {
239
 
                // Set the flag to indicate we have a connection to XMDS
240
 
                Properties.Settings.Default.XmdsLastConnection = DateTime.Now;
241
 
 
242
 
                // What file type were we getting
243
 
                if (currentFileList.type == "layout")
244
 
                {  
245
 
                    // Decode this byte[] into a string and stick it in the file.
246
 
                    string layoutXml = Encoding.UTF8.GetString(e.Result);
247
 
 
248
 
                    // MD5 it to make sure it arrived ok
249
 
                    string md5sum = Hashes.MD5(layoutXml);
250
 
 
251
 
                    if (md5sum != currentFileList.md5)
252
 
                    {
253
 
                        // We need to get this file again
254
 
                    }
255
 
 
256
 
                    // We know it is finished and that we need to write to a file
257
 
                    try
258
 
                    {
259
 
                        string fullPath = Properties.Settings.Default.LibraryPath + @"\" + currentFileList.path + ".xlf";
260
 
                        
261
 
                        StreamWriter sw = new StreamWriter(File.Open(fullPath, FileMode.Create, FileAccess.Write, FileShare.Read), Encoding.UTF8);
262
 
                        sw.Write(layoutXml);
263
 
                        sw.Close();
264
 
 
265
 
                        // This file is complete
266
 
                        currentFileList.complete = true;
267
 
                    }
268
 
                    catch (IOException ex)
269
 
                    {
270
 
                        //What do we do if we cant open the file stream?
271
 
                        System.Diagnostics.Debug.WriteLine(ex.Message, "FileCollector - GetFileCompleted");
272
 
                    }
273
 
 
274
 
                    // Fire a layout complete event
275
 
                    LayoutFileChanged(currentFileList.path + ".xlf");
276
 
 
277
 
                    System.Diagnostics.Trace.WriteLine(String.Format("File downloaded: {0}", currentFileList.path), "xmdsFile_GetFileCompleted");
278
 
 
279
 
                    currentFile++;
280
 
                }
281
 
                else
282
 
                {
283
 
                    // Need to write to the file - in append mode
284
 
                    FileStream fs = new FileStream(Properties.Settings.Default.LibraryPath + @"\" + currentFileList.path, FileMode.Append, FileAccess.Write);
285
 
 
286
 
                    fs.Write(e.Result, 0, e.Result.Length);
287
 
                    fs.Close();
288
 
                    fs.Dispose();
289
 
 
290
 
                    // Increment the chunkOffset by the amount we just asked for
291
 
                    currentFileList.chunkOffset = currentFileList.chunkOffset + currentFileList.chunkSize;
292
 
 
293
 
                    // Has the offset reached the total size?
294
 
                    if (currentFileList.size > currentFileList.chunkOffset)
295
 
                    {
296
 
                        int remaining = currentFileList.size - currentFileList.chunkOffset;
297
 
                        // There is still more to come
298
 
                        if (remaining < currentFileList.chunkSize)
299
 
                        {
300
 
                            // Get the remaining
301
 
                            currentFileList.chunkSize = remaining;
302
 
                        }
303
 
                    }
304
 
                    else
305
 
                    {
306
 
                        // Do we need to do some sort of MD5 here? To make sure we got what we should have
307
 
                        fs = new FileStream(Properties.Settings.Default.LibraryPath + @"\" + currentFileList.path, FileMode.Open, FileAccess.Read);
308
 
 
309
 
                        string md5sum = Hashes.MD5(fs);
310
 
 
311
 
                        if (md5sum != currentFileList.md5)
312
 
                        {
313
 
                            // We need to get this file again
314
 
                            try
315
 
                            {
316
 
                                File.Delete(Properties.Settings.Default.LibraryPath + @"\" + currentFileList.path);
317
 
                            }
318
 
                            catch (Exception ex)
319
 
                            {
320
 
                                // Unable to delete incorrect file
321
 
                                // Hopefully we will overwrite it
322
 
                                System.Diagnostics.Debug.WriteLine(ex.Message);
323
 
                            }
324
 
 
325
 
                            //Reset the chunk offset (otherwise we will try to get this file again - but from the beginning (no so good)
326
 
                            currentFileList.chunkOffset = 0;
327
 
 
328
 
                            System.Diagnostics.Trace.WriteLine(String.Format("Error getting file {0}, HASH failed. Starting again", currentFileList.path));
 
221
            try
 
222
            {
 
223
                // Expect new schedule XML
 
224
                if (e.Error != null)
 
225
                {
 
226
                    //There was an error - what do we do?
 
227
                    // Log it
 
228
                    System.Diagnostics.Debug.WriteLine(e.Error.Message, "WS Error");
 
229
 
 
230
                    System.Diagnostics.Trace.WriteLine(String.Format("Error From WebService Get File. File=[{1}], Error=[{0}], Try No [{2}]", e.Error.Message, _currentFileList.path, _currentFileList.retrys));
 
231
 
 
232
                    // Retry?
 
233
                    if (_currentFileList.retrys < 5)
 
234
                    {
 
235
                        // Increment the Retrys
 
236
                        _currentFileList.retrys++;
 
237
 
 
238
                        // Try again
 
239
                        GetFile();
 
240
                    }
 
241
                    else
 
242
                    {
 
243
                        // Blacklist this file
 
244
                        string[] mediaPath = _currentFileList.path.Split('.');
 
245
                        string mediaId = mediaPath[0];
 
246
 
 
247
                        BlackList blackList = new BlackList();
 
248
                        blackList.Add(_currentFileList.path, BlackListType.All, String.Format("Max number of retrys failed. BlackListing for all displays. Error {0}", e.Error.Message));
 
249
 
 
250
                        // Move on
 
251
                        _currentFile++;
 
252
                    }
 
253
                }
 
254
                else
 
255
                {
 
256
                    // Set the flag to indicate we have a connection to XMDS
 
257
                    Properties.Settings.Default.XmdsLastConnection = DateTime.Now;
 
258
 
 
259
                    // What file type were we getting
 
260
                    if (_currentFileList.type == "layout")
 
261
                    {
 
262
                        // Decode this byte[] into a string and stick it in the file.
 
263
                        string layoutXml = Encoding.UTF8.GetString(e.Result);
 
264
                       
 
265
 
 
266
                        // We know it is finished and that we need to write to a file
 
267
                        try
 
268
                        {
 
269
                            string fullPath = Properties.Settings.Default.LibraryPath + @"\" + _currentFileList.path + ".xlf";
 
270
 
 
271
                            StreamWriter sw = new StreamWriter(File.Open(fullPath, FileMode.Create, FileAccess.Write, FileShare.Read), Encoding.Default);
 
272
                            sw.Write(layoutXml);
 
273
                            sw.Close();
 
274
 
 
275
                            // This file is complete
 
276
                            _currentFileList.complete = true;
 
277
                        }
 
278
                        catch (IOException ex)
 
279
                        {
 
280
                            //What do we do if we cant open the file stream?
 
281
                            System.Diagnostics.Debug.WriteLine(ex.Message, "FileCollector - GetFileCompleted");
 
282
                        }
 
283
 
 
284
                        // Check it
 
285
                        String md5sum = _cacheManager.GetMD5(_currentFileList.path + ".xlf");
 
286
 
 
287
                        System.Diagnostics.Debug.WriteLine(String.Format("Comparing MD5 of completed download [{0}] with given MD5 [{1}]", md5sum, _currentFileList.md5));
 
288
 
 
289
                        // TODO: What if the MD5 is different?
 
290
                        if (md5sum != _currentFileList.md5)
 
291
                            System.Diagnostics.Trace.WriteLine(new LogMessage("xmdsFile_GetFileCompleted", String.Format("Incorrect MD5 for file: {0}", _currentFileList.path)));
 
292
 
 
293
                        // Fire a layout complete event
 
294
                        LayoutFileChanged(_currentFileList.path + ".xlf");
 
295
 
 
296
                        System.Diagnostics.Trace.WriteLine(String.Format("File downloaded: {0}", _currentFileList.path), "xmdsFile_GetFileCompleted");
 
297
 
 
298
                        _currentFile++;
 
299
                    }
 
300
                    else
 
301
                    {
 
302
                        // Need to write to the file - in append mode
 
303
                        FileStream fs = new FileStream(Properties.Settings.Default.LibraryPath + @"\" + _currentFileList.path, FileMode.Append, FileAccess.Write);
 
304
 
 
305
                        fs.Write(e.Result, 0, e.Result.Length);
 
306
                        fs.Close();
 
307
                        fs.Dispose();
 
308
 
 
309
                        // Increment the chunkOffset by the amount we just asked for
 
310
                        _currentFileList.chunkOffset = _currentFileList.chunkOffset + _currentFileList.chunkSize;
 
311
 
 
312
                        // Has the offset reached the total size?
 
313
                        if (_currentFileList.size > _currentFileList.chunkOffset)
 
314
                        {
 
315
                            int remaining = _currentFileList.size - _currentFileList.chunkOffset;
 
316
                            // There is still more to come
 
317
                            if (remaining < _currentFileList.chunkSize)
 
318
                            {
 
319
                                // Get the remaining
 
320
                                _currentFileList.chunkSize = remaining;
 
321
                            }
329
322
                        }
330
323
                        else
331
324
                        {
332
 
                            // This file is complete
333
 
                            currentFileList.complete = true;
334
 
 
335
 
                            // Fire the File Complete event
336
 
                            MediaFileChanged(currentFileList.path);
337
 
 
338
 
                            System.Diagnostics.Debug.WriteLine(string.Format("File downloaded: {0}", currentFileList.path));
339
 
 
340
 
                            // All the file has been recieved. Move on to the next file.
341
 
                            currentFile++;
 
325
                            String md5sum = _cacheManager.GetMD5(_currentFileList.path);
 
326
 
 
327
                            System.Diagnostics.Debug.WriteLine(String.Format("Comparing MD5 of completed download [{0}] with given MD5 [{1}]", md5sum, _currentFileList.md5));
 
328
 
 
329
                            if (md5sum != _currentFileList.md5)
 
330
                            {
 
331
                                // We need to get this file again
 
332
                                try
 
333
                                {
 
334
                                    File.Delete(Properties.Settings.Default.LibraryPath + @"\" + _currentFileList.path);
 
335
                                }
 
336
                                catch (Exception ex)
 
337
                                {
 
338
                                    // Unable to delete incorrect file
 
339
                                    // Hopefully we will overwrite it
 
340
                                    System.Diagnostics.Debug.WriteLine(ex.Message);
 
341
                                }
 
342
 
 
343
                                // Reset the chunk offset (otherwise we will try to get this file again - but from the beginning (no so good)
 
344
                                _currentFileList.chunkOffset = 0;
 
345
 
 
346
                                System.Diagnostics.Trace.WriteLine(String.Format("Error getting file {0}, HASH failed. Starting again", _currentFileList.path));
 
347
                            }
 
348
                            else
 
349
                            {
 
350
                                // This file is complete
 
351
                                _currentFileList.complete = true;
 
352
 
 
353
                                // Fire the File Complete event
 
354
                                MediaFileChanged(_currentFileList.path);
 
355
 
 
356
                                System.Diagnostics.Debug.WriteLine(string.Format("File downloaded: {0}", _currentFileList.path));
 
357
 
 
358
                                // All the file has been recieved. Move on to the next file.
 
359
                                _currentFile++;
 
360
                            }
342
361
                        }
343
362
                    }
 
363
 
 
364
                    // Before we get the next file render any waiting events
 
365
                    System.Windows.Forms.Application.DoEvents();
344
366
                }
345
 
 
346
 
                // Before we get the next file render any waiting events
347
 
                System.Windows.Forms.Application.DoEvents();
348
 
 
349
 
                GetFile();
350
 
            }
 
367
            }
 
368
            catch (Exception ex)
 
369
            {
 
370
                Trace.WriteLine(new LogMessage("xmdsFile_GetFileCompleted", "Unable to get the file. Exception: " + ex.Message));
 
371
 
 
372
                // Consider this file complete because we couldn't write it....
 
373
                _currentFileList.complete = true;
 
374
                _currentFile++;
 
375
            }
 
376
 
 
377
            // Get the next file
 
378
            GetFile();
351
379
        }
352
380
 
353
381
        /// <summary>
355
383
        /// </summary>
356
384
        public void GetFile()
357
385
        {
358
 
            if (currentFile > (files.Count - 1))
 
386
            if (_currentFile > (files.Count - 1))
359
387
            {
360
388
                System.Diagnostics.Debug.WriteLine(String.Format("Finished Recieving {0} files", files.Count));
361
389
 
369
397
            else
370
398
            {
371
399
                // Get the current file into the currentfilelist if the current one is finished
372
 
                if (currentFileList.complete)
 
400
                if (_currentFileList.complete)
373
401
                {
374
 
                    currentFileList = files[currentFile];
 
402
                    _currentFileList = files[_currentFile];
375
403
                }
376
404
 
377
 
                System.Diagnostics.Debug.WriteLine(String.Format("Getting the file : {0} chunk : {1}", currentFileList.path, currentFileList.chunkOffset.ToString()));
 
405
                System.Diagnostics.Debug.WriteLine(String.Format("Getting the file : {0} chunk : {1}", _currentFileList.path, _currentFileList.chunkOffset.ToString()));
378
406
 
379
407
                // Request the file
380
 
                xmdsFile.GetFileAsync(Properties.Settings.Default.ServerKey, hardwareKey.Key, currentFileList.path, currentFileList.type, currentFileList.chunkOffset, currentFileList.chunkSize, Properties.Settings.Default.Version);
 
408
                xmdsFile.GetFileAsync(Properties.Settings.Default.ServerKey, hardwareKey.Key, _currentFileList.path, _currentFileList.type, _currentFileList.chunkOffset, _currentFileList.chunkSize, Properties.Settings.Default.Version);
381
409
 
382
 
                currentFileList.downloading = true;
 
410
                _currentFileList.downloading = true;
383
411
            }
384
412
        }
385
413
 
400
428
        private XmlDocument xml;
401
429
        private HardwareKey hardwareKey;
402
430
        private Collection<FileList> files;
403
 
        private int currentFile;
404
 
        private FileList currentFileList;
 
431
        private int _currentFile;
 
432
        private FileList _currentFileList;
405
433
        private xmds.xmds xmdsFile;
406
434
 
407
435
        public event LayoutFileChangedDelegate LayoutFileChanged;