Changed the retry function in PithosClient to use the TPL
[pithos-ms-client] / trunk / Pithos.Core / PithosWorkflow.cs
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel.Composition;
4 using System.Linq;
5 using System.Runtime.InteropServices;
6 using System.Text;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using Pithos.Interfaces;
10 using System.IO;
11
12 namespace Pithos.Core
13 {
14     [Export(typeof(IPithosWorkflow))]
15     public class PithosWorkflow:IPithosWorkflow
16     {
17         [Import]
18         public IPithosSettings Settings { get; set; }
19
20         [Import]
21         public IStatusKeeper StatusKeeper { get; set; }
22
23         public FileStatus SetFileStatus(string path, FileStatus status)
24         {
25             if (String.IsNullOrWhiteSpace(path))
26                 throw new ArgumentNullException("path", "The path parameter must not be emtpy");
27
28             var oldStatus=StatusKeeper.GetFileStatus(path);
29
30             if (oldStatus == status)
31                 return oldStatus;
32
33             switch(oldStatus)
34             {
35                 case FileStatus.Unchanged :
36                     break;
37                 case FileStatus.Created:
38                     if (status == FileStatus.Modified)
39                         return oldStatus;
40                     break;
41                 case FileStatus.Modified:
42                 case FileStatus.Renamed:
43                     if (status == FileStatus.Created)
44                         return oldStatus;
45                     break;
46                 case FileStatus.Deleted:
47                     return oldStatus;                    
48             }
49             StatusKeeper.SetFileStatus(path, status);
50             return status;
51         }
52
53         public void ClearFileStatus(string path)
54         {
55             if (String.IsNullOrWhiteSpace(path))
56                 throw new ArgumentNullException("path", "The path parameter must not be emtpy");
57
58             StatusKeeper.ClearFileStatus(path);
59         }
60
61         public void RaiseChangeNotification(string path)
62         {
63             if (String.IsNullOrWhiteSpace(path))
64                 throw new ArgumentNullException("path", "The path parameter must not be emtpy");
65             
66             if (!Directory.Exists(path ) && !File.Exists(path))
67                 throw new FileNotFoundException("The specified file or path does not exist",path);
68             
69
70             IntPtr pathPointer = Marshal.StringToCoTaskMemAuto(path);
71
72             try
73             {
74                 NativeMethods.SHChangeNotify(HChangeNotifyEventID.SHCNE_UPDATEITEM,
75                                              HChangeNotifyFlags.SHCNF_PATHW | HChangeNotifyFlags.SHCNF_FLUSHNOWAIT,
76                                              pathPointer, IntPtr.Zero);                
77             }
78             finally
79             {
80                 Marshal.FreeHGlobal(pathPointer);
81             }
82
83         }
84
85         public Task<FileStream> OpenStreamWithWaiting(string path)
86         {
87             if (String.IsNullOrWhiteSpace(path))
88                 throw new ArgumentNullException("path","The path parameter must not be emtpy");
89
90             if (!File.Exists(path))
91                 throw new FileNotFoundException("The specified file or path does not exist", path);
92
93             return new Task<FileStream>(() =>
94                     {
95                         int counter = 0;
96                         while (true)
97                         {
98                             try
99                             {
100                                 var stream=File.OpenRead(path);
101                                 return stream;                                
102                             }
103                             catch (Exception ex)
104                             {
105                                 Thread.Sleep(500);
106                                 if (++counter > 10)
107                                     throw;
108                             }
109                         }
110                     });
111         }
112     }
113 }