root / trunk / Pithos.Network / CloudFilesClient.cs @ ff26eb71
History | View | Annotate | Download (51.5 kB)
1 | 5ce54458 | Panagiotis Kanavos | // **CloudFilesClient** provides a simple client interface to CloudFiles and Pithos |
---|---|---|---|
2 | 5ce54458 | Panagiotis Kanavos | // |
3 | 5ce54458 | Panagiotis Kanavos | // The class provides methods to upload/download files, delete files, manage containers |
4 | 5ce54458 | Panagiotis Kanavos | |
5 | 5ce54458 | Panagiotis Kanavos | |
6 | 5ce54458 | Panagiotis Kanavos | using System; |
7 | d78cbf09 | Panagiotis Kanavos | using System.Collections.Generic; |
8 | d78cbf09 | Panagiotis Kanavos | using System.ComponentModel.Composition; |
9 | d78cbf09 | Panagiotis Kanavos | using System.Diagnostics.Contracts; |
10 | d78cbf09 | Panagiotis Kanavos | using System.IO; |
11 | d78cbf09 | Panagiotis Kanavos | using System.Linq; |
12 | d78cbf09 | Panagiotis Kanavos | using System.Net; |
13 | d78cbf09 | Panagiotis Kanavos | using System.Security.Cryptography; |
14 | d78cbf09 | Panagiotis Kanavos | using System.Text; |
15 | b5061ac8 | Panagiotis Kanavos | using System.Threading.Tasks; |
16 | d78cbf09 | Panagiotis Kanavos | using Newtonsoft.Json; |
17 | d78cbf09 | Panagiotis Kanavos | using Pithos.Interfaces; |
18 | 5120f3cb | Panagiotis Kanavos | using log4net; |
19 | d78cbf09 | Panagiotis Kanavos | |
20 | d78cbf09 | Panagiotis Kanavos | namespace Pithos.Network |
21 | d78cbf09 | Panagiotis Kanavos | { |
22 | d78cbf09 | Panagiotis Kanavos | [Export(typeof(ICloudClient))] |
23 | d78cbf09 | Panagiotis Kanavos | public class CloudFilesClient:ICloudClient |
24 | d78cbf09 | Panagiotis Kanavos | { |
25 | 5ce54458 | Panagiotis Kanavos | //CloudFilesClient uses *_baseClient* internally to communicate with the server |
26 | 5ce54458 | Panagiotis Kanavos | //RestClient provides a REST-friendly interface over the standard WebClient. |
27 | 9c4346c9 | Panagiotis Kanavos | private RestClient _baseClient; |
28 | 5ce54458 | Panagiotis Kanavos | |
29 | c53aa229 | Panagiotis Kanavos | |
30 | 5ce54458 | Panagiotis Kanavos | //During authentication the client provides a UserName |
31 | d78cbf09 | Panagiotis Kanavos | public string UserName { get; set; } |
32 | 5ce54458 | Panagiotis Kanavos | |
33 | 5ce54458 | Panagiotis Kanavos | //and and ApiKey to the server |
34 | 5ce54458 | Panagiotis Kanavos | public string ApiKey { get; set; } |
35 | 5ce54458 | Panagiotis Kanavos | |
36 | 5ce54458 | Panagiotis Kanavos | //And receives an authentication Token. This token must be provided in ALL other operations, |
37 | 5ce54458 | Panagiotis Kanavos | //in the X-Auth-Token header |
38 | c53aa229 | Panagiotis Kanavos | private string _token; |
39 | c53aa229 | Panagiotis Kanavos | public string Token |
40 | c53aa229 | Panagiotis Kanavos | { |
41 | c53aa229 | Panagiotis Kanavos | get { return _token; } |
42 | c53aa229 | Panagiotis Kanavos | set |
43 | c53aa229 | Panagiotis Kanavos | { |
44 | c53aa229 | Panagiotis Kanavos | _token = value; |
45 | c53aa229 | Panagiotis Kanavos | _baseClient.Headers["X-Auth-Token"] = value; |
46 | c53aa229 | Panagiotis Kanavos | } |
47 | c53aa229 | Panagiotis Kanavos | } |
48 | c53aa229 | Panagiotis Kanavos | |
49 | 5ce54458 | Panagiotis Kanavos | //The client also receives a StorageUrl after authentication. All subsequent operations must |
50 | 5ce54458 | Panagiotis Kanavos | //use this url |
51 | 5ce54458 | Panagiotis Kanavos | public Uri StorageUrl { get; set; } |
52 | cfed7823 | Panagiotis Kanavos | |
53 | c53aa229 | Panagiotis Kanavos | |
54 | cfed7823 | Panagiotis Kanavos | protected Uri RootAddressUri { get; set; } |
55 | cfed7823 | Panagiotis Kanavos | |
56 | c53aa229 | Panagiotis Kanavos | private Uri _proxy; |
57 | c53aa229 | Panagiotis Kanavos | public Uri Proxy |
58 | c53aa229 | Panagiotis Kanavos | { |
59 | c53aa229 | Panagiotis Kanavos | get { return _proxy; } |
60 | c53aa229 | Panagiotis Kanavos | set |
61 | c53aa229 | Panagiotis Kanavos | { |
62 | c53aa229 | Panagiotis Kanavos | _proxy = value; |
63 | c53aa229 | Panagiotis Kanavos | if (_baseClient != null) |
64 | c53aa229 | Panagiotis Kanavos | _baseClient.Proxy = new WebProxy(value); |
65 | c53aa229 | Panagiotis Kanavos | } |
66 | c53aa229 | Panagiotis Kanavos | } |
67 | b5061ac8 | Panagiotis Kanavos | |
68 | b5061ac8 | Panagiotis Kanavos | public double DownloadPercentLimit { get; set; } |
69 | b5061ac8 | Panagiotis Kanavos | public double UploadPercentLimit { get; set; } |
70 | 79736291 | Panagiotis Kanavos | |
71 | 79736291 | Panagiotis Kanavos | public string AuthenticationUrl { get; set; } |
72 | 79736291 | Panagiotis Kanavos | |
73 | 1482f9ad | Panagiotis Kanavos | |
74 | 1482f9ad | Panagiotis Kanavos | public string VersionPath |
75 | 1482f9ad | Panagiotis Kanavos | { |
76 | 1482f9ad | Panagiotis Kanavos | get { return UsePithos ? "v1" : "v1.0"; } |
77 | 1482f9ad | Panagiotis Kanavos | } |
78 | 2c053915 | Panagiotis Kanavos | |
79 | 2c053915 | Panagiotis Kanavos | public bool UsePithos { get; set; } |
80 | d78cbf09 | Panagiotis Kanavos | |
81 | 3c43ec9b | Panagiotis Kanavos | |
82 | 5120f3cb | Panagiotis Kanavos | private static readonly ILog Log = LogManager.GetLogger("CloudFilesClient"); |
83 | 5120f3cb | Panagiotis Kanavos | |
84 | c53aa229 | Panagiotis Kanavos | public CloudFilesClient(string userName, string apiKey) |
85 | d78cbf09 | Panagiotis Kanavos | { |
86 | c53aa229 | Panagiotis Kanavos | UserName = userName; |
87 | c53aa229 | Panagiotis Kanavos | ApiKey = apiKey; |
88 | c53aa229 | Panagiotis Kanavos | } |
89 | c53aa229 | Panagiotis Kanavos | |
90 | c53aa229 | Panagiotis Kanavos | public CloudFilesClient(AccountInfo accountInfo) |
91 | c53aa229 | Panagiotis Kanavos | { |
92 | c53aa229 | Panagiotis Kanavos | if (accountInfo==null) |
93 | c53aa229 | Panagiotis Kanavos | throw new ArgumentNullException("accountInfo"); |
94 | c53aa229 | Panagiotis Kanavos | Contract.Ensures(!String.IsNullOrWhiteSpace(Token)); |
95 | c53aa229 | Panagiotis Kanavos | Contract.Ensures(StorageUrl != null); |
96 | cfed7823 | Panagiotis Kanavos | Contract.Ensures(_baseClient != null); |
97 | c53aa229 | Panagiotis Kanavos | Contract.Ensures(RootAddressUri != null); |
98 | cfed7823 | Panagiotis Kanavos | Contract.EndContractBlock(); |
99 | cfed7823 | Panagiotis Kanavos | |
100 | c53aa229 | Panagiotis Kanavos | _baseClient = new RestClient |
101 | c53aa229 | Panagiotis Kanavos | { |
102 | c53aa229 | Panagiotis Kanavos | BaseAddress = accountInfo.StorageUri.ToString(), |
103 | c53aa229 | Panagiotis Kanavos | Timeout = 10000, |
104 | c53aa229 | Panagiotis Kanavos | Retries = 3 |
105 | c53aa229 | Panagiotis Kanavos | }; |
106 | c53aa229 | Panagiotis Kanavos | StorageUrl = accountInfo.StorageUri; |
107 | c53aa229 | Panagiotis Kanavos | Token = accountInfo.Token; |
108 | c53aa229 | Panagiotis Kanavos | UserName = accountInfo.UserName; |
109 | c53aa229 | Panagiotis Kanavos | |
110 | c53aa229 | Panagiotis Kanavos | //Get the root address (StorageUrl without the account) |
111 | c53aa229 | Panagiotis Kanavos | var storageUrl = StorageUrl.AbsoluteUri; |
112 | c53aa229 | Panagiotis Kanavos | var usernameIndex = storageUrl.LastIndexOf(UserName); |
113 | c53aa229 | Panagiotis Kanavos | var rootUrl = storageUrl.Substring(0, usernameIndex); |
114 | c53aa229 | Panagiotis Kanavos | RootAddressUri = new Uri(rootUrl); |
115 | c53aa229 | Panagiotis Kanavos | } |
116 | d78cbf09 | Panagiotis Kanavos | |
117 | 3c43ec9b | Panagiotis Kanavos | |
118 | c53aa229 | Panagiotis Kanavos | public AccountInfo Authenticate() |
119 | c53aa229 | Panagiotis Kanavos | { |
120 | c53aa229 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(UserName)) |
121 | c53aa229 | Panagiotis Kanavos | throw new InvalidOperationException("UserName is empty"); |
122 | c53aa229 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(ApiKey)) |
123 | c53aa229 | Panagiotis Kanavos | throw new InvalidOperationException("ApiKey is empty"); |
124 | c53aa229 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(AuthenticationUrl)) |
125 | c53aa229 | Panagiotis Kanavos | throw new InvalidOperationException("AuthenticationUrl is empty"); |
126 | c53aa229 | Panagiotis Kanavos | Contract.Ensures(!String.IsNullOrWhiteSpace(Token)); |
127 | c53aa229 | Panagiotis Kanavos | Contract.Ensures(StorageUrl != null); |
128 | c53aa229 | Panagiotis Kanavos | Contract.Ensures(_baseClient != null); |
129 | c53aa229 | Panagiotis Kanavos | Contract.Ensures(RootAddressUri != null); |
130 | c53aa229 | Panagiotis Kanavos | Contract.EndContractBlock(); |
131 | c53aa229 | Panagiotis Kanavos | |
132 | c53aa229 | Panagiotis Kanavos | |
133 | c53aa229 | Panagiotis Kanavos | Log.InfoFormat("[AUTHENTICATE] Start for {0}", UserName); |
134 | d78cbf09 | Panagiotis Kanavos | |
135 | 9c4346c9 | Panagiotis Kanavos | using (var authClient = new RestClient{BaseAddress=AuthenticationUrl}) |
136 | cd7c162f | Panagiotis Kanavos | { |
137 | 4d301e8e | Panagiotis Kanavos | if (Proxy != null) |
138 | 4d301e8e | Panagiotis Kanavos | authClient.Proxy = new WebProxy(Proxy); |
139 | d78cbf09 | Panagiotis Kanavos | |
140 | cfed7823 | Panagiotis Kanavos | Contract.Assume(authClient.Headers!=null); |
141 | cfed7823 | Panagiotis Kanavos | |
142 | 4d301e8e | Panagiotis Kanavos | authClient.Headers.Add("X-Auth-User", UserName); |
143 | 4d301e8e | Panagiotis Kanavos | authClient.Headers.Add("X-Auth-Key", ApiKey); |
144 | 0eea575a | Panagiotis Kanavos | |
145 | cd7c162f | Panagiotis Kanavos | authClient.DownloadStringWithRetry(VersionPath, 3); |
146 | 0eea575a | Panagiotis Kanavos | |
147 | 4d301e8e | Panagiotis Kanavos | authClient.AssertStatusOK("Authentication failed"); |
148 | 0eea575a | Panagiotis Kanavos | |
149 | cd7c162f | Panagiotis Kanavos | var storageUrl = authClient.GetHeaderValue("X-Storage-Url"); |
150 | 0eea575a | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(storageUrl)) |
151 | 0eea575a | Panagiotis Kanavos | throw new InvalidOperationException("Failed to obtain storage url"); |
152 | c53aa229 | Panagiotis Kanavos | |
153 | c53aa229 | Panagiotis Kanavos | _baseClient = new RestClient |
154 | c53aa229 | Panagiotis Kanavos | { |
155 | c53aa229 | Panagiotis Kanavos | BaseAddress = storageUrl, |
156 | c53aa229 | Panagiotis Kanavos | Timeout = 10000, |
157 | c53aa229 | Panagiotis Kanavos | Retries = 3 |
158 | c53aa229 | Panagiotis Kanavos | }; |
159 | c53aa229 | Panagiotis Kanavos | |
160 | 0eea575a | Panagiotis Kanavos | StorageUrl = new Uri(storageUrl); |
161 | d9643dd6 | Panagiotis Kanavos | |
162 | cfed7823 | Panagiotis Kanavos | //Get the root address (StorageUrl without the account) |
163 | cfed7823 | Panagiotis Kanavos | var usernameIndex=storageUrl.LastIndexOf(UserName); |
164 | cfed7823 | Panagiotis Kanavos | var rootUrl = storageUrl.Substring(0, usernameIndex); |
165 | cfed7823 | Panagiotis Kanavos | RootAddressUri = new Uri(rootUrl); |
166 | cfed7823 | Panagiotis Kanavos | |
167 | 4d301e8e | Panagiotis Kanavos | var token = authClient.GetHeaderValue("X-Auth-Token"); |
168 | b6c72f62 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(token)) |
169 | b6c72f62 | Panagiotis Kanavos | throw new InvalidOperationException("Failed to obtain token url"); |
170 | b6c72f62 | Panagiotis Kanavos | Token = token; |
171 | c53aa229 | Panagiotis Kanavos | |
172 | b6c72f62 | Panagiotis Kanavos | } |
173 | d78cbf09 | Panagiotis Kanavos | |
174 | c53aa229 | Panagiotis Kanavos | Log.InfoFormat("[AUTHENTICATE] End for {0}", UserName); |
175 | 0bd56b7c | Panagiotis Kanavos | |
176 | 9c4346c9 | Panagiotis Kanavos | |
177 | c53aa229 | Panagiotis Kanavos | return new AccountInfo {StorageUri = StorageUrl, Token = Token, UserName = UserName}; |
178 | 2c053915 | Panagiotis Kanavos | |
179 | b5061ac8 | Panagiotis Kanavos | } |
180 | d78cbf09 | Panagiotis Kanavos | |
181 | d78cbf09 | Panagiotis Kanavos | |
182 | cfed7823 | Panagiotis Kanavos | |
183 | cfed7823 | Panagiotis Kanavos | public IList<ContainerInfo> ListContainers(string account) |
184 | 9c4346c9 | Panagiotis Kanavos | { |
185 | 9c4346c9 | Panagiotis Kanavos | using (var client = new RestClient(_baseClient)) |
186 | 9c4346c9 | Panagiotis Kanavos | { |
187 | cfed7823 | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
188 | cfed7823 | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
189 | cfed7823 | Panagiotis Kanavos | |
190 | 9c4346c9 | Panagiotis Kanavos | client.Parameters.Clear(); |
191 | 9c4346c9 | Panagiotis Kanavos | client.Parameters.Add("format", "json"); |
192 | 5ce54458 | Panagiotis Kanavos | var content = client.DownloadStringWithRetry("", 3); |
193 | 9c4346c9 | Panagiotis Kanavos | client.AssertStatusOK("List Containers failed"); |
194 | 9c4346c9 | Panagiotis Kanavos | |
195 | 9c4346c9 | Panagiotis Kanavos | if (client.StatusCode == HttpStatusCode.NoContent) |
196 | 9c4346c9 | Panagiotis Kanavos | return new List<ContainerInfo>(); |
197 | 9c4346c9 | Panagiotis Kanavos | var infos = JsonConvert.DeserializeObject<IList<ContainerInfo>>(content); |
198 | 5750d7cc | Panagiotis Kanavos | |
199 | 5750d7cc | Panagiotis Kanavos | foreach (var info in infos) |
200 | 5750d7cc | Panagiotis Kanavos | { |
201 | 5750d7cc | Panagiotis Kanavos | info.Account = account; |
202 | 5750d7cc | Panagiotis Kanavos | } |
203 | 9c4346c9 | Panagiotis Kanavos | return infos; |
204 | 9c4346c9 | Panagiotis Kanavos | } |
205 | 4d301e8e | Panagiotis Kanavos | |
206 | d78cbf09 | Panagiotis Kanavos | } |
207 | d78cbf09 | Panagiotis Kanavos | |
208 | cfed7823 | Panagiotis Kanavos | private string GetAccountUrl(string account) |
209 | cfed7823 | Panagiotis Kanavos | { |
210 | cfed7823 | Panagiotis Kanavos | return new Uri(this.RootAddressUri, new Uri(account,UriKind.Relative)).AbsoluteUri; |
211 | cfed7823 | Panagiotis Kanavos | } |
212 | cfed7823 | Panagiotis Kanavos | |
213 | cfed7823 | Panagiotis Kanavos | public IList<ShareAccountInfo> ListSharingAccounts(DateTime? since=null) |
214 | cfed7823 | Panagiotis Kanavos | { |
215 | 5120f3cb | Panagiotis Kanavos | using (log4net.ThreadContext.Stacks["Share"].Push("List Accounts")) |
216 | cfed7823 | Panagiotis Kanavos | { |
217 | 5120f3cb | Panagiotis Kanavos | if (Log.IsDebugEnabled) Log.DebugFormat("START"); |
218 | cfed7823 | Panagiotis Kanavos | |
219 | 5120f3cb | Panagiotis Kanavos | using (var client = new RestClient(_baseClient)) |
220 | 5120f3cb | Panagiotis Kanavos | { |
221 | 5120f3cb | Panagiotis Kanavos | client.Parameters.Clear(); |
222 | 5120f3cb | Panagiotis Kanavos | client.Parameters.Add("format", "json"); |
223 | 5120f3cb | Panagiotis Kanavos | client.IfModifiedSince = since; |
224 | cfed7823 | Panagiotis Kanavos | |
225 | 5120f3cb | Panagiotis Kanavos | //Extract the username from the base address |
226 | 5120f3cb | Panagiotis Kanavos | client.BaseAddress = RootAddressUri.AbsoluteUri; |
227 | cfed7823 | Panagiotis Kanavos | |
228 | 5120f3cb | Panagiotis Kanavos | var content = client.DownloadStringWithRetry(@"", 3); |
229 | cfed7823 | Panagiotis Kanavos | |
230 | 5120f3cb | Panagiotis Kanavos | client.AssertStatusOK("ListSharingAccounts failed"); |
231 | 5120f3cb | Panagiotis Kanavos | |
232 | 5120f3cb | Panagiotis Kanavos | //If the result is empty, return an empty list, |
233 | 5120f3cb | Panagiotis Kanavos | var infos = String.IsNullOrWhiteSpace(content) |
234 | 5120f3cb | Panagiotis Kanavos | ? new List<ShareAccountInfo>() |
235 | 5120f3cb | Panagiotis Kanavos | //Otherwise deserialize the account list into a list of ShareAccountInfos |
236 | 5120f3cb | Panagiotis Kanavos | : JsonConvert.DeserializeObject<IList<ShareAccountInfo>>(content); |
237 | 5120f3cb | Panagiotis Kanavos | |
238 | 5120f3cb | Panagiotis Kanavos | Log.DebugFormat("END"); |
239 | 5120f3cb | Panagiotis Kanavos | return infos; |
240 | 5120f3cb | Panagiotis Kanavos | } |
241 | cfed7823 | Panagiotis Kanavos | } |
242 | cfed7823 | Panagiotis Kanavos | } |
243 | cfed7823 | Panagiotis Kanavos | |
244 | 5ce54458 | Panagiotis Kanavos | //Request listing of all objects in a container modified since a specific time. |
245 | 5ce54458 | Panagiotis Kanavos | //If the *since* value is missing, return all objects |
246 | cfed7823 | Panagiotis Kanavos | public IList<ObjectInfo> ListSharedObjects(DateTime? since = null) |
247 | cfed7823 | Panagiotis Kanavos | { |
248 | cfed7823 | Panagiotis Kanavos | |
249 | 5120f3cb | Panagiotis Kanavos | using (log4net.ThreadContext.Stacks["Share"].Push("List Objects")) |
250 | cfed7823 | Panagiotis Kanavos | { |
251 | 5120f3cb | Panagiotis Kanavos | if (Log.IsDebugEnabled) Log.DebugFormat("START"); |
252 | 5120f3cb | Panagiotis Kanavos | |
253 | 5120f3cb | Panagiotis Kanavos | var objects = new List<ObjectInfo>(); |
254 | 5120f3cb | Panagiotis Kanavos | var accounts = ListSharingAccounts(since); |
255 | 5120f3cb | Panagiotis Kanavos | foreach (var account in accounts) |
256 | cfed7823 | Panagiotis Kanavos | { |
257 | 5120f3cb | Panagiotis Kanavos | var containers = ListContainers(account.name); |
258 | 5120f3cb | Panagiotis Kanavos | foreach (var container in containers) |
259 | 5120f3cb | Panagiotis Kanavos | { |
260 | 0bd56b7c | Panagiotis Kanavos | var containerObjects = ListObjects(account.name, container.Name, null); |
261 | 5120f3cb | Panagiotis Kanavos | objects.AddRange(containerObjects); |
262 | 5120f3cb | Panagiotis Kanavos | } |
263 | cfed7823 | Panagiotis Kanavos | } |
264 | 5120f3cb | Panagiotis Kanavos | if (Log.IsDebugEnabled) Log.DebugFormat("END"); |
265 | 5120f3cb | Panagiotis Kanavos | return objects; |
266 | cfed7823 | Panagiotis Kanavos | } |
267 | cfed7823 | Panagiotis Kanavos | } |
268 | cfed7823 | Panagiotis Kanavos | |
269 | ff26eb71 | Panagiotis Kanavos | public void SetTags(ObjectInfo target,IDictionary<string,string> tags) |
270 | ff26eb71 | Panagiotis Kanavos | { |
271 | ff26eb71 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(Token)) |
272 | ff26eb71 | Panagiotis Kanavos | throw new InvalidOperationException("The Token is not set"); |
273 | ff26eb71 | Panagiotis Kanavos | if (StorageUrl == null) |
274 | ff26eb71 | Panagiotis Kanavos | throw new InvalidOperationException("The StorageUrl is not set"); |
275 | ff26eb71 | Panagiotis Kanavos | if (target == null) |
276 | ff26eb71 | Panagiotis Kanavos | throw new ArgumentNullException("target"); |
277 | ff26eb71 | Panagiotis Kanavos | Contract.EndContractBlock(); |
278 | ff26eb71 | Panagiotis Kanavos | |
279 | ff26eb71 | Panagiotis Kanavos | using (log4net.ThreadContext.Stacks["Share"].Push("Share Object")) |
280 | ff26eb71 | Panagiotis Kanavos | { |
281 | ff26eb71 | Panagiotis Kanavos | if (Log.IsDebugEnabled) Log.DebugFormat("START"); |
282 | ff26eb71 | Panagiotis Kanavos | |
283 | ff26eb71 | Panagiotis Kanavos | using (var client = new RestClient(_baseClient)) |
284 | ff26eb71 | Panagiotis Kanavos | { |
285 | ff26eb71 | Panagiotis Kanavos | |
286 | ff26eb71 | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(target.Account); |
287 | ff26eb71 | Panagiotis Kanavos | |
288 | ff26eb71 | Panagiotis Kanavos | client.Parameters.Clear(); |
289 | ff26eb71 | Panagiotis Kanavos | client.Parameters.Add("update", ""); |
290 | ff26eb71 | Panagiotis Kanavos | |
291 | ff26eb71 | Panagiotis Kanavos | foreach (var tag in tags) |
292 | ff26eb71 | Panagiotis Kanavos | { |
293 | ff26eb71 | Panagiotis Kanavos | var headerTag = String.Format("X-Object-Meta-{0}", tag.Key); |
294 | ff26eb71 | Panagiotis Kanavos | client.Headers.Add(headerTag, tag.Value); |
295 | ff26eb71 | Panagiotis Kanavos | } |
296 | ff26eb71 | Panagiotis Kanavos | |
297 | ff26eb71 | Panagiotis Kanavos | var content = client.DownloadStringWithRetry(target.Container, 3); |
298 | ff26eb71 | Panagiotis Kanavos | |
299 | ff26eb71 | Panagiotis Kanavos | |
300 | ff26eb71 | Panagiotis Kanavos | client.AssertStatusOK("SetTags failed"); |
301 | ff26eb71 | Panagiotis Kanavos | //If the status is NOT ACCEPTED we have a problem |
302 | ff26eb71 | Panagiotis Kanavos | if (client.StatusCode != HttpStatusCode.Accepted) |
303 | ff26eb71 | Panagiotis Kanavos | { |
304 | ff26eb71 | Panagiotis Kanavos | Log.Error("Failed to set tags"); |
305 | ff26eb71 | Panagiotis Kanavos | throw new Exception("Failed to set tags"); |
306 | ff26eb71 | Panagiotis Kanavos | } |
307 | ff26eb71 | Panagiotis Kanavos | |
308 | ff26eb71 | Panagiotis Kanavos | if (Log.IsDebugEnabled) Log.DebugFormat("END"); |
309 | ff26eb71 | Panagiotis Kanavos | } |
310 | ff26eb71 | Panagiotis Kanavos | } |
311 | ff26eb71 | Panagiotis Kanavos | |
312 | ff26eb71 | Panagiotis Kanavos | |
313 | ff26eb71 | Panagiotis Kanavos | } |
314 | ff26eb71 | Panagiotis Kanavos | |
315 | cfed7823 | Panagiotis Kanavos | public void ShareObject(string account, string container, string objectName, string shareTo, bool read, bool write) |
316 | cfed7823 | Panagiotis Kanavos | { |
317 | cfed7823 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(Token)) |
318 | cfed7823 | Panagiotis Kanavos | throw new InvalidOperationException("The Token is not set"); |
319 | cfed7823 | Panagiotis Kanavos | if (StorageUrl==null) |
320 | cfed7823 | Panagiotis Kanavos | throw new InvalidOperationException("The StorageUrl is not set"); |
321 | cfed7823 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
322 | cfed7823 | Panagiotis Kanavos | throw new ArgumentNullException("container"); |
323 | cfed7823 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(objectName)) |
324 | cfed7823 | Panagiotis Kanavos | throw new ArgumentNullException("objectName"); |
325 | cfed7823 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(account)) |
326 | cfed7823 | Panagiotis Kanavos | throw new ArgumentNullException("account"); |
327 | cfed7823 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(shareTo)) |
328 | cfed7823 | Panagiotis Kanavos | throw new ArgumentNullException("shareTo"); |
329 | cfed7823 | Panagiotis Kanavos | Contract.EndContractBlock(); |
330 | cfed7823 | Panagiotis Kanavos | |
331 | 5120f3cb | Panagiotis Kanavos | using (log4net.ThreadContext.Stacks["Share"].Push("Share Object")) |
332 | cfed7823 | Panagiotis Kanavos | { |
333 | 5120f3cb | Panagiotis Kanavos | if (Log.IsDebugEnabled) Log.DebugFormat("START"); |
334 | 5120f3cb | Panagiotis Kanavos | |
335 | 5120f3cb | Panagiotis Kanavos | using (var client = new RestClient(_baseClient)) |
336 | 5120f3cb | Panagiotis Kanavos | { |
337 | cfed7823 | Panagiotis Kanavos | |
338 | 5120f3cb | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
339 | cfed7823 | Panagiotis Kanavos | |
340 | 5120f3cb | Panagiotis Kanavos | client.Parameters.Clear(); |
341 | 5120f3cb | Panagiotis Kanavos | client.Parameters.Add("format", "json"); |
342 | 5120f3cb | Panagiotis Kanavos | |
343 | 5120f3cb | Panagiotis Kanavos | string permission = ""; |
344 | 5120f3cb | Panagiotis Kanavos | if (write) |
345 | 5120f3cb | Panagiotis Kanavos | permission = String.Format("write={0}", shareTo); |
346 | 5120f3cb | Panagiotis Kanavos | else if (read) |
347 | 5120f3cb | Panagiotis Kanavos | permission = String.Format("read={0}", shareTo); |
348 | 5120f3cb | Panagiotis Kanavos | client.Headers.Add("X-Object-Sharing", permission); |
349 | cfed7823 | Panagiotis Kanavos | |
350 | 5120f3cb | Panagiotis Kanavos | var content = client.DownloadStringWithRetry(container, 3); |
351 | cfed7823 | Panagiotis Kanavos | |
352 | 5120f3cb | Panagiotis Kanavos | client.AssertStatusOK("ShareObject failed"); |
353 | cfed7823 | Panagiotis Kanavos | |
354 | 5120f3cb | Panagiotis Kanavos | //If the result is empty, return an empty list, |
355 | 5120f3cb | Panagiotis Kanavos | var infos = String.IsNullOrWhiteSpace(content) |
356 | 5120f3cb | Panagiotis Kanavos | ? new List<ObjectInfo>() |
357 | 5120f3cb | Panagiotis Kanavos | //Otherwise deserialize the object list into a list of ObjectInfos |
358 | 5120f3cb | Panagiotis Kanavos | : JsonConvert.DeserializeObject<IList<ObjectInfo>>(content); |
359 | 5120f3cb | Panagiotis Kanavos | |
360 | 5120f3cb | Panagiotis Kanavos | if (Log.IsDebugEnabled) Log.DebugFormat("END"); |
361 | 5120f3cb | Panagiotis Kanavos | } |
362 | cfed7823 | Panagiotis Kanavos | } |
363 | cfed7823 | Panagiotis Kanavos | |
364 | 5120f3cb | Panagiotis Kanavos | |
365 | cfed7823 | Panagiotis Kanavos | } |
366 | cfed7823 | Panagiotis Kanavos | |
367 | 0bd56b7c | Panagiotis Kanavos | public AccountInfo GetAccountPolicies(AccountInfo accountInfo) |
368 | 0bd56b7c | Panagiotis Kanavos | { |
369 | 0bd56b7c | Panagiotis Kanavos | if (accountInfo==null) |
370 | 0bd56b7c | Panagiotis Kanavos | throw new ArgumentNullException("accountInfo"); |
371 | 0bd56b7c | Panagiotis Kanavos | Contract.EndContractBlock(); |
372 | 0bd56b7c | Panagiotis Kanavos | |
373 | 0bd56b7c | Panagiotis Kanavos | using (log4net.ThreadContext.Stacks["Account"].Push("GetPolicies")) |
374 | 0bd56b7c | Panagiotis Kanavos | { |
375 | 0bd56b7c | Panagiotis Kanavos | if (Log.IsDebugEnabled) Log.DebugFormat("START"); |
376 | 0bd56b7c | Panagiotis Kanavos | |
377 | 0bd56b7c | Panagiotis Kanavos | using (var client = new RestClient(_baseClient)) |
378 | 0bd56b7c | Panagiotis Kanavos | { |
379 | 0bd56b7c | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(accountInfo.UserName)) |
380 | 0bd56b7c | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(accountInfo.UserName); |
381 | 0bd56b7c | Panagiotis Kanavos | |
382 | 0bd56b7c | Panagiotis Kanavos | client.Parameters.Clear(); |
383 | 0bd56b7c | Panagiotis Kanavos | client.Parameters.Add("format", "json"); |
384 | 0bd56b7c | Panagiotis Kanavos | client.Head(String.Empty, 3); |
385 | 0bd56b7c | Panagiotis Kanavos | |
386 | 0bd56b7c | Panagiotis Kanavos | var quotaValue=client.ResponseHeaders["X-Account-Policy-Quota"]; |
387 | 0bd56b7c | Panagiotis Kanavos | var bytesValue= client.ResponseHeaders["X-Account-Bytes-Used"]; |
388 | 0bd56b7c | Panagiotis Kanavos | |
389 | 0bd56b7c | Panagiotis Kanavos | long quota, bytes; |
390 | 0bd56b7c | Panagiotis Kanavos | if (long.TryParse(quotaValue, out quota)) |
391 | 0bd56b7c | Panagiotis Kanavos | accountInfo.Quota = quota; |
392 | 0bd56b7c | Panagiotis Kanavos | if (long.TryParse(bytesValue, out bytes)) |
393 | 0bd56b7c | Panagiotis Kanavos | accountInfo.BytesUsed = bytes; |
394 | 0bd56b7c | Panagiotis Kanavos | |
395 | 0bd56b7c | Panagiotis Kanavos | return accountInfo; |
396 | 0bd56b7c | Panagiotis Kanavos | |
397 | 0bd56b7c | Panagiotis Kanavos | } |
398 | 0bd56b7c | Panagiotis Kanavos | |
399 | 0bd56b7c | Panagiotis Kanavos | } |
400 | 0bd56b7c | Panagiotis Kanavos | } |
401 | 0bd56b7c | Panagiotis Kanavos | |
402 | cfed7823 | Panagiotis Kanavos | |
403 | cfed7823 | Panagiotis Kanavos | public IList<ObjectInfo> ListObjects(string account, string container, DateTime? since = null) |
404 | d78cbf09 | Panagiotis Kanavos | { |
405 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
406 | 9c4346c9 | Panagiotis Kanavos | throw new ArgumentNullException("container"); |
407 | 9c4346c9 | Panagiotis Kanavos | Contract.EndContractBlock(); |
408 | d78cbf09 | Panagiotis Kanavos | |
409 | 5120f3cb | Panagiotis Kanavos | using (log4net.ThreadContext.Stacks["Objects"].Push("List")) |
410 | 9c4346c9 | Panagiotis Kanavos | { |
411 | 5120f3cb | Panagiotis Kanavos | if (Log.IsDebugEnabled) Log.DebugFormat("START"); |
412 | cfed7823 | Panagiotis Kanavos | |
413 | 5120f3cb | Panagiotis Kanavos | using (var client = new RestClient(_baseClient)) |
414 | 5120f3cb | Panagiotis Kanavos | { |
415 | 5120f3cb | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
416 | 5120f3cb | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
417 | 4d301e8e | Panagiotis Kanavos | |
418 | 5120f3cb | Panagiotis Kanavos | client.Parameters.Clear(); |
419 | 5120f3cb | Panagiotis Kanavos | client.Parameters.Add("format", "json"); |
420 | 5120f3cb | Panagiotis Kanavos | client.IfModifiedSince = since; |
421 | 5120f3cb | Panagiotis Kanavos | var content = client.DownloadStringWithRetry(container, 3); |
422 | 4d301e8e | Panagiotis Kanavos | |
423 | 5120f3cb | Panagiotis Kanavos | client.AssertStatusOK("ListObjects failed"); |
424 | d78cbf09 | Panagiotis Kanavos | |
425 | 5120f3cb | Panagiotis Kanavos | //If the result is empty, return an empty list, |
426 | 5120f3cb | Panagiotis Kanavos | var infos = String.IsNullOrWhiteSpace(content) |
427 | 5120f3cb | Panagiotis Kanavos | ? new List<ObjectInfo>() |
428 | 5120f3cb | Panagiotis Kanavos | //Otherwise deserialize the object list into a list of ObjectInfos |
429 | 5120f3cb | Panagiotis Kanavos | : JsonConvert.DeserializeObject<IList<ObjectInfo>>(content); |
430 | 5120f3cb | Panagiotis Kanavos | |
431 | 5120f3cb | Panagiotis Kanavos | foreach (var info in infos) |
432 | 5120f3cb | Panagiotis Kanavos | { |
433 | 5120f3cb | Panagiotis Kanavos | info.Container = container; |
434 | 5120f3cb | Panagiotis Kanavos | info.Account = account; |
435 | 5120f3cb | Panagiotis Kanavos | } |
436 | 5120f3cb | Panagiotis Kanavos | if (Log.IsDebugEnabled) Log.DebugFormat("START"); |
437 | 5120f3cb | Panagiotis Kanavos | return infos; |
438 | cfed7823 | Panagiotis Kanavos | } |
439 | 9c4346c9 | Panagiotis Kanavos | } |
440 | d78cbf09 | Panagiotis Kanavos | } |
441 | d78cbf09 | Panagiotis Kanavos | |
442 | 637bc368 | Panagiotis Kanavos | |
443 | 5bcf6d70 | Panagiotis Kanavos | |
444 | cfed7823 | Panagiotis Kanavos | public IList<ObjectInfo> ListObjects(string account, string container, string folder, DateTime? since = null) |
445 | 637bc368 | Panagiotis Kanavos | { |
446 | 637bc368 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
447 | 9c4346c9 | Panagiotis Kanavos | throw new ArgumentNullException("container"); |
448 | 9c4346c9 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(folder)) |
449 | 9c4346c9 | Panagiotis Kanavos | throw new ArgumentNullException("folder"); |
450 | 9c4346c9 | Panagiotis Kanavos | Contract.EndContractBlock(); |
451 | 637bc368 | Panagiotis Kanavos | |
452 | 5120f3cb | Panagiotis Kanavos | using (log4net.ThreadContext.Stacks["Objects"].Push("List")) |
453 | 9c4346c9 | Panagiotis Kanavos | { |
454 | 5120f3cb | Panagiotis Kanavos | if (Log.IsDebugEnabled) Log.DebugFormat("START"); |
455 | cfed7823 | Panagiotis Kanavos | |
456 | 5120f3cb | Panagiotis Kanavos | using (var client = new RestClient(_baseClient)) |
457 | 5120f3cb | Panagiotis Kanavos | { |
458 | 5120f3cb | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
459 | 5120f3cb | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
460 | 4d301e8e | Panagiotis Kanavos | |
461 | 5120f3cb | Panagiotis Kanavos | client.Parameters.Clear(); |
462 | 5120f3cb | Panagiotis Kanavos | client.Parameters.Add("format", "json"); |
463 | 5120f3cb | Panagiotis Kanavos | client.Parameters.Add("path", folder); |
464 | 5120f3cb | Panagiotis Kanavos | client.IfModifiedSince = since; |
465 | 5120f3cb | Panagiotis Kanavos | var content = client.DownloadStringWithRetry(container, 3); |
466 | 5120f3cb | Panagiotis Kanavos | client.AssertStatusOK("ListObjects failed"); |
467 | 5bcf6d70 | Panagiotis Kanavos | |
468 | 5120f3cb | Panagiotis Kanavos | var infos = JsonConvert.DeserializeObject<IList<ObjectInfo>>(content); |
469 | 5120f3cb | Panagiotis Kanavos | |
470 | 5120f3cb | Panagiotis Kanavos | if (Log.IsDebugEnabled) Log.DebugFormat("END"); |
471 | 5120f3cb | Panagiotis Kanavos | return infos; |
472 | 5120f3cb | Panagiotis Kanavos | } |
473 | 9c4346c9 | Panagiotis Kanavos | } |
474 | 5bcf6d70 | Panagiotis Kanavos | } |
475 | 5bcf6d70 | Panagiotis Kanavos | |
476 | d15e99b4 | Panagiotis Kanavos | |
477 | cfed7823 | Panagiotis Kanavos | public bool ContainerExists(string account, string container) |
478 | d78cbf09 | Panagiotis Kanavos | { |
479 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
480 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
481 | cfed7823 | Panagiotis Kanavos | Contract.EndContractBlock(); |
482 | cfed7823 | Panagiotis Kanavos | |
483 | 5120f3cb | Panagiotis Kanavos | using (log4net.ThreadContext.Stacks["Containters"].Push("Exists")) |
484 | d78cbf09 | Panagiotis Kanavos | { |
485 | 5120f3cb | Panagiotis Kanavos | if (Log.IsDebugEnabled) Log.DebugFormat("START"); |
486 | cfed7823 | Panagiotis Kanavos | |
487 | 5120f3cb | Panagiotis Kanavos | using (var client = new RestClient(_baseClient)) |
488 | 9c4346c9 | Panagiotis Kanavos | { |
489 | 5120f3cb | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
490 | 5120f3cb | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
491 | 5120f3cb | Panagiotis Kanavos | |
492 | 5120f3cb | Panagiotis Kanavos | client.Parameters.Clear(); |
493 | 5120f3cb | Panagiotis Kanavos | client.Head(container, 3); |
494 | 5120f3cb | Panagiotis Kanavos | |
495 | 5120f3cb | Panagiotis Kanavos | bool result; |
496 | 5120f3cb | Panagiotis Kanavos | switch (client.StatusCode) |
497 | 5120f3cb | Panagiotis Kanavos | { |
498 | 5120f3cb | Panagiotis Kanavos | case HttpStatusCode.OK: |
499 | 5120f3cb | Panagiotis Kanavos | case HttpStatusCode.NoContent: |
500 | 5120f3cb | Panagiotis Kanavos | result=true; |
501 | 5120f3cb | Panagiotis Kanavos | break; |
502 | 5120f3cb | Panagiotis Kanavos | case HttpStatusCode.NotFound: |
503 | 5120f3cb | Panagiotis Kanavos | result=false; |
504 | 5120f3cb | Panagiotis Kanavos | break; |
505 | 5120f3cb | Panagiotis Kanavos | default: |
506 | 5120f3cb | Panagiotis Kanavos | throw CreateWebException("ContainerExists", client.StatusCode); |
507 | 5120f3cb | Panagiotis Kanavos | } |
508 | 5120f3cb | Panagiotis Kanavos | if (Log.IsDebugEnabled) Log.DebugFormat("END"); |
509 | 5120f3cb | Panagiotis Kanavos | |
510 | 5120f3cb | Panagiotis Kanavos | return result; |
511 | 9c4346c9 | Panagiotis Kanavos | } |
512 | 5120f3cb | Panagiotis Kanavos | |
513 | d78cbf09 | Panagiotis Kanavos | } |
514 | d78cbf09 | Panagiotis Kanavos | } |
515 | d78cbf09 | Panagiotis Kanavos | |
516 | cfed7823 | Panagiotis Kanavos | public bool ObjectExists(string account, string container, string objectName) |
517 | d78cbf09 | Panagiotis Kanavos | { |
518 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
519 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
520 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(objectName)) |
521 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("objectName", "The objectName property can't be empty"); |
522 | cfed7823 | Panagiotis Kanavos | Contract.EndContractBlock(); |
523 | cfed7823 | Panagiotis Kanavos | |
524 | 9c4346c9 | Panagiotis Kanavos | using (var client = new RestClient(_baseClient)) |
525 | d78cbf09 | Panagiotis Kanavos | { |
526 | cfed7823 | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
527 | cfed7823 | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
528 | cfed7823 | Panagiotis Kanavos | |
529 | 9c4346c9 | Panagiotis Kanavos | client.Parameters.Clear(); |
530 | 9c4346c9 | Panagiotis Kanavos | client.Head(container + "/" + objectName, 3); |
531 | 9c4346c9 | Panagiotis Kanavos | |
532 | 9c4346c9 | Panagiotis Kanavos | switch (client.StatusCode) |
533 | 9c4346c9 | Panagiotis Kanavos | { |
534 | 9c4346c9 | Panagiotis Kanavos | case HttpStatusCode.OK: |
535 | 9c4346c9 | Panagiotis Kanavos | case HttpStatusCode.NoContent: |
536 | 9c4346c9 | Panagiotis Kanavos | return true; |
537 | 9c4346c9 | Panagiotis Kanavos | case HttpStatusCode.NotFound: |
538 | 9c4346c9 | Panagiotis Kanavos | return false; |
539 | 9c4346c9 | Panagiotis Kanavos | default: |
540 | 9c4346c9 | Panagiotis Kanavos | throw CreateWebException("ObjectExists", client.StatusCode); |
541 | 9c4346c9 | Panagiotis Kanavos | } |
542 | d78cbf09 | Panagiotis Kanavos | } |
543 | 9c4346c9 | Panagiotis Kanavos | |
544 | d78cbf09 | Panagiotis Kanavos | } |
545 | d78cbf09 | Panagiotis Kanavos | |
546 | cfed7823 | Panagiotis Kanavos | public ObjectInfo GetObjectInfo(string account, string container, string objectName) |
547 | d78cbf09 | Panagiotis Kanavos | { |
548 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
549 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
550 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(objectName)) |
551 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("objectName", "The objectName property can't be empty"); |
552 | cfed7823 | Panagiotis Kanavos | Contract.EndContractBlock(); |
553 | d78cbf09 | Panagiotis Kanavos | |
554 | 5120f3cb | Panagiotis Kanavos | using (log4net.ThreadContext.Stacks["Objects"].Push("GetObjectInfo")) |
555 | 5120f3cb | Panagiotis Kanavos | { |
556 | 5120f3cb | Panagiotis Kanavos | |
557 | 5120f3cb | Panagiotis Kanavos | using (var client = new RestClient(_baseClient)) |
558 | 9c4346c9 | Panagiotis Kanavos | { |
559 | 5120f3cb | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
560 | 5120f3cb | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
561 | 5120f3cb | Panagiotis Kanavos | try |
562 | 5120f3cb | Panagiotis Kanavos | { |
563 | 5120f3cb | Panagiotis Kanavos | client.Parameters.Clear(); |
564 | d78cbf09 | Panagiotis Kanavos | |
565 | 5120f3cb | Panagiotis Kanavos | client.Head(container + "/" + objectName, 3); |
566 | d78cbf09 | Panagiotis Kanavos | |
567 | 5120f3cb | Panagiotis Kanavos | if (client.TimedOut) |
568 | 5120f3cb | Panagiotis Kanavos | return ObjectInfo.Empty; |
569 | 9c4346c9 | Panagiotis Kanavos | |
570 | 5120f3cb | Panagiotis Kanavos | switch (client.StatusCode) |
571 | 5120f3cb | Panagiotis Kanavos | { |
572 | 5120f3cb | Panagiotis Kanavos | case HttpStatusCode.OK: |
573 | 5120f3cb | Panagiotis Kanavos | case HttpStatusCode.NoContent: |
574 | 5120f3cb | Panagiotis Kanavos | var keys = client.ResponseHeaders.AllKeys.AsQueryable(); |
575 | 5120f3cb | Panagiotis Kanavos | var tags = (from key in keys |
576 | 5120f3cb | Panagiotis Kanavos | where key.StartsWith("X-Object-Meta-") |
577 | 5120f3cb | Panagiotis Kanavos | let name = key.Substring(14) |
578 | 5120f3cb | Panagiotis Kanavos | select new {Name = name, Value = client.ResponseHeaders[name]}) |
579 | 5120f3cb | Panagiotis Kanavos | .ToDictionary(t => t.Name, t => t.Value); |
580 | 5120f3cb | Panagiotis Kanavos | var extensions = (from key in keys |
581 | 5120f3cb | Panagiotis Kanavos | where key.StartsWith("X-Object-") && !key.StartsWith("X-Object-Meta-") |
582 | 5120f3cb | Panagiotis Kanavos | select new {Name = key, Value = client.ResponseHeaders[key]}) |
583 | 5120f3cb | Panagiotis Kanavos | .ToDictionary(t => t.Name, t => t.Value); |
584 | 5120f3cb | Panagiotis Kanavos | var info = new ObjectInfo |
585 | 5120f3cb | Panagiotis Kanavos | { |
586 | 7b0a5fec | Panagiotis Kanavos | Account = account, |
587 | 7b0a5fec | Panagiotis Kanavos | Container = container, |
588 | 5120f3cb | Panagiotis Kanavos | Name = objectName, |
589 | 5120f3cb | Panagiotis Kanavos | Hash = client.GetHeaderValue("ETag"), |
590 | 5120f3cb | Panagiotis Kanavos | Content_Type = client.GetHeaderValue("Content-Type"), |
591 | 7b0a5fec | Panagiotis Kanavos | Bytes = Convert.ToInt64(client.GetHeaderValue("Content-Length")), |
592 | 5120f3cb | Panagiotis Kanavos | Tags = tags, |
593 | 5120f3cb | Panagiotis Kanavos | Last_Modified = client.LastModified, |
594 | 5120f3cb | Panagiotis Kanavos | Extensions = extensions |
595 | 5120f3cb | Panagiotis Kanavos | }; |
596 | 5120f3cb | Panagiotis Kanavos | return info; |
597 | 5120f3cb | Panagiotis Kanavos | case HttpStatusCode.NotFound: |
598 | 5120f3cb | Panagiotis Kanavos | return ObjectInfo.Empty; |
599 | 5120f3cb | Panagiotis Kanavos | default: |
600 | 5120f3cb | Panagiotis Kanavos | throw new WebException( |
601 | 5120f3cb | Panagiotis Kanavos | String.Format("[FAIL] GetObjectInfo for {0} failed with unexpected status code {1}", |
602 | 5120f3cb | Panagiotis Kanavos | objectName, client.StatusCode)); |
603 | 5120f3cb | Panagiotis Kanavos | } |
604 | 5120f3cb | Panagiotis Kanavos | |
605 | 5120f3cb | Panagiotis Kanavos | } |
606 | 5120f3cb | Panagiotis Kanavos | catch (RetryException) |
607 | 9c4346c9 | Panagiotis Kanavos | { |
608 | 5120f3cb | Panagiotis Kanavos | Log.WarnFormat("[RETRY FAIL] GetObjectInfo for {0} failed."); |
609 | 5120f3cb | Panagiotis Kanavos | return ObjectInfo.Empty; |
610 | 9c4346c9 | Panagiotis Kanavos | } |
611 | 5120f3cb | Panagiotis Kanavos | catch (WebException e) |
612 | 5120f3cb | Panagiotis Kanavos | { |
613 | 5120f3cb | Panagiotis Kanavos | Log.Error( |
614 | 5120f3cb | Panagiotis Kanavos | String.Format("[FAIL] GetObjectInfo for {0} failed with unexpected status code {1}", |
615 | 5120f3cb | Panagiotis Kanavos | objectName, client.StatusCode), e); |
616 | 5120f3cb | Panagiotis Kanavos | throw; |
617 | 5120f3cb | Panagiotis Kanavos | } |
618 | 5120f3cb | Panagiotis Kanavos | } |
619 | d78cbf09 | Panagiotis Kanavos | } |
620 | 9c4346c9 | Panagiotis Kanavos | |
621 | d78cbf09 | Panagiotis Kanavos | } |
622 | d78cbf09 | Panagiotis Kanavos | |
623 | cfed7823 | Panagiotis Kanavos | public void CreateFolder(string account, string container, string folder) |
624 | 10523ad9 | Panagiotis Kanavos | { |
625 | 10523ad9 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
626 | 10523ad9 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
627 | 10523ad9 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(folder)) |
628 | 10523ad9 | Panagiotis Kanavos | throw new ArgumentNullException("folder", "The folder property can't be empty"); |
629 | cfed7823 | Panagiotis Kanavos | Contract.EndContractBlock(); |
630 | 10523ad9 | Panagiotis Kanavos | |
631 | 10523ad9 | Panagiotis Kanavos | var folderUrl=String.Format("{0}/{1}",container,folder); |
632 | 9c4346c9 | Panagiotis Kanavos | using (var client = new RestClient(_baseClient)) |
633 | 9c4346c9 | Panagiotis Kanavos | { |
634 | cfed7823 | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
635 | cfed7823 | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
636 | cfed7823 | Panagiotis Kanavos | |
637 | 9c4346c9 | Panagiotis Kanavos | client.Parameters.Clear(); |
638 | 9c4346c9 | Panagiotis Kanavos | client.Headers.Add("Content-Type", @"application/directory"); |
639 | 9c4346c9 | Panagiotis Kanavos | client.Headers.Add("Content-Length", "0"); |
640 | 9c4346c9 | Panagiotis Kanavos | client.PutWithRetry(folderUrl, 3); |
641 | 10523ad9 | Panagiotis Kanavos | |
642 | 9c4346c9 | Panagiotis Kanavos | if (client.StatusCode != HttpStatusCode.Created && client.StatusCode != HttpStatusCode.Accepted) |
643 | 9c4346c9 | Panagiotis Kanavos | throw CreateWebException("CreateFolder", client.StatusCode); |
644 | 9c4346c9 | Panagiotis Kanavos | } |
645 | 10523ad9 | Panagiotis Kanavos | } |
646 | 10523ad9 | Panagiotis Kanavos | |
647 | cfed7823 | Panagiotis Kanavos | public ContainerInfo GetContainerInfo(string account, string container) |
648 | d78cbf09 | Panagiotis Kanavos | { |
649 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
650 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
651 | cfed7823 | Panagiotis Kanavos | Contract.EndContractBlock(); |
652 | cfed7823 | Panagiotis Kanavos | |
653 | 9c4346c9 | Panagiotis Kanavos | using (var client = new RestClient(_baseClient)) |
654 | d78cbf09 | Panagiotis Kanavos | { |
655 | cfed7823 | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
656 | cfed7823 | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
657 | cfed7823 | Panagiotis Kanavos | |
658 | 9c4346c9 | Panagiotis Kanavos | client.Head(container); |
659 | 9c4346c9 | Panagiotis Kanavos | switch (client.StatusCode) |
660 | 9c4346c9 | Panagiotis Kanavos | { |
661 | 5ce54458 | Panagiotis Kanavos | case HttpStatusCode.OK: |
662 | 9c4346c9 | Panagiotis Kanavos | case HttpStatusCode.NoContent: |
663 | 27361404 | Panagiotis Kanavos | var keys = client.ResponseHeaders.AllKeys.AsQueryable(); |
664 | 27361404 | Panagiotis Kanavos | var tags = (from key in keys |
665 | 27361404 | Panagiotis Kanavos | where key.StartsWith("X-Container-Meta-") |
666 | 27361404 | Panagiotis Kanavos | let name = key.Substring(14) |
667 | 27361404 | Panagiotis Kanavos | select new { Name = name, Value = client.ResponseHeaders[name] }) |
668 | 27361404 | Panagiotis Kanavos | .ToDictionary(t => t.Name, t => t.Value); |
669 | 27361404 | Panagiotis Kanavos | var policies= (from key in keys |
670 | 27361404 | Panagiotis Kanavos | where key.StartsWith("X-Container-Policy-") |
671 | 27361404 | Panagiotis Kanavos | let name = key.Substring(14) |
672 | 27361404 | Panagiotis Kanavos | select new { Name = name, Value = client.ResponseHeaders[name] }) |
673 | 27361404 | Panagiotis Kanavos | .ToDictionary(t => t.Name, t => t.Value); |
674 | 27361404 | Panagiotis Kanavos | |
675 | 9c4346c9 | Panagiotis Kanavos | var containerInfo = new ContainerInfo |
676 | 9c4346c9 | Panagiotis Kanavos | { |
677 | 42800be8 | Panagiotis Kanavos | Account=account, |
678 | 9c4346c9 | Panagiotis Kanavos | Name = container, |
679 | 9c4346c9 | Panagiotis Kanavos | Count = |
680 | 9c4346c9 | Panagiotis Kanavos | long.Parse(client.GetHeaderValue("X-Container-Object-Count")), |
681 | 5ce54458 | Panagiotis Kanavos | Bytes = long.Parse(client.GetHeaderValue("X-Container-Bytes-Used")), |
682 | 5ce54458 | Panagiotis Kanavos | BlockHash = client.GetHeaderValue("X-Container-Block-Hash"), |
683 | 42800be8 | Panagiotis Kanavos | BlockSize=int.Parse(client.GetHeaderValue("X-Container-Block-Size")), |
684 | 27361404 | Panagiotis Kanavos | Last_Modified=client.LastModified, |
685 | 27361404 | Panagiotis Kanavos | Tags=tags, |
686 | 27361404 | Panagiotis Kanavos | Policies=policies |
687 | 9c4346c9 | Panagiotis Kanavos | }; |
688 | 27361404 | Panagiotis Kanavos | |
689 | 27361404 | Panagiotis Kanavos | |
690 | 9c4346c9 | Panagiotis Kanavos | return containerInfo; |
691 | 9c4346c9 | Panagiotis Kanavos | case HttpStatusCode.NotFound: |
692 | 9c4346c9 | Panagiotis Kanavos | return ContainerInfo.Empty; |
693 | 9c4346c9 | Panagiotis Kanavos | default: |
694 | 9c4346c9 | Panagiotis Kanavos | throw CreateWebException("GetContainerInfo", client.StatusCode); |
695 | 9c4346c9 | Panagiotis Kanavos | } |
696 | d78cbf09 | Panagiotis Kanavos | } |
697 | d78cbf09 | Panagiotis Kanavos | } |
698 | d78cbf09 | Panagiotis Kanavos | |
699 | cfed7823 | Panagiotis Kanavos | public void CreateContainer(string account, string container) |
700 | cfed7823 | Panagiotis Kanavos | { |
701 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
702 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
703 | cfed7823 | Panagiotis Kanavos | Contract.EndContractBlock(); |
704 | cfed7823 | Panagiotis Kanavos | |
705 | 9c4346c9 | Panagiotis Kanavos | using (var client = new RestClient(_baseClient)) |
706 | 9c4346c9 | Panagiotis Kanavos | { |
707 | cfed7823 | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
708 | cfed7823 | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
709 | cfed7823 | Panagiotis Kanavos | |
710 | 9c4346c9 | Panagiotis Kanavos | client.PutWithRetry(container, 3); |
711 | 9c4346c9 | Panagiotis Kanavos | var expectedCodes = new[] {HttpStatusCode.Created, HttpStatusCode.Accepted, HttpStatusCode.OK}; |
712 | 9c4346c9 | Panagiotis Kanavos | if (!expectedCodes.Contains(client.StatusCode)) |
713 | 9c4346c9 | Panagiotis Kanavos | throw CreateWebException("CreateContainer", client.StatusCode); |
714 | 9c4346c9 | Panagiotis Kanavos | } |
715 | d78cbf09 | Panagiotis Kanavos | } |
716 | d78cbf09 | Panagiotis Kanavos | |
717 | cfed7823 | Panagiotis Kanavos | public void DeleteContainer(string account, string container) |
718 | 2c053915 | Panagiotis Kanavos | { |
719 | 2c053915 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
720 | 2c053915 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
721 | cfed7823 | Panagiotis Kanavos | Contract.EndContractBlock(); |
722 | cfed7823 | Panagiotis Kanavos | |
723 | 9c4346c9 | Panagiotis Kanavos | using (var client = new RestClient(_baseClient)) |
724 | 9c4346c9 | Panagiotis Kanavos | { |
725 | cfed7823 | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
726 | cfed7823 | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
727 | cfed7823 | Panagiotis Kanavos | |
728 | 9c4346c9 | Panagiotis Kanavos | client.DeleteWithRetry(container, 3); |
729 | 9c4346c9 | Panagiotis Kanavos | var expectedCodes = new[] {HttpStatusCode.NotFound, HttpStatusCode.NoContent}; |
730 | 9c4346c9 | Panagiotis Kanavos | if (!expectedCodes.Contains(client.StatusCode)) |
731 | 9c4346c9 | Panagiotis Kanavos | throw CreateWebException("DeleteContainer", client.StatusCode); |
732 | 9c4346c9 | Panagiotis Kanavos | } |
733 | 2c053915 | Panagiotis Kanavos | |
734 | 2c053915 | Panagiotis Kanavos | } |
735 | 2c053915 | Panagiotis Kanavos | |
736 | 5bcf6d70 | Panagiotis Kanavos | /// <summary> |
737 | 5bcf6d70 | Panagiotis Kanavos | /// |
738 | 5bcf6d70 | Panagiotis Kanavos | /// </summary> |
739 | cfed7823 | Panagiotis Kanavos | /// <param name="account"></param> |
740 | 5bcf6d70 | Panagiotis Kanavos | /// <param name="container"></param> |
741 | 5bcf6d70 | Panagiotis Kanavos | /// <param name="objectName"></param> |
742 | 283809f3 | Panagiotis Kanavos | /// <param name="fileName"></param> |
743 | 5bcf6d70 | Panagiotis Kanavos | /// <returns></returns> |
744 | 5ce54458 | Panagiotis Kanavos | /// <remarks>This method should have no timeout or a very long one</remarks> |
745 | 5ce54458 | Panagiotis Kanavos | //Asynchronously download the object specified by *objectName* in a specific *container* to |
746 | 5ce54458 | Panagiotis Kanavos | // a local file |
747 | cfed7823 | Panagiotis Kanavos | public Task GetObject(string account, string container, string objectName, string fileName) |
748 | d78cbf09 | Panagiotis Kanavos | { |
749 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
750 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
751 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(objectName)) |
752 | 5ce54458 | Panagiotis Kanavos | throw new ArgumentNullException("objectName", "The objectName property can't be empty"); |
753 | 5ce54458 | Panagiotis Kanavos | Contract.EndContractBlock(); |
754 | 5ce54458 | Panagiotis Kanavos | |
755 | 283809f3 | Panagiotis Kanavos | try |
756 | 283809f3 | Panagiotis Kanavos | { |
757 | 5ce54458 | Panagiotis Kanavos | //WebClient, and by extension RestClient, are not thread-safe. Create a new RestClient |
758 | 5ce54458 | Panagiotis Kanavos | //object to avoid concurrency errors. |
759 | 5ce54458 | Panagiotis Kanavos | // |
760 | 5ce54458 | Panagiotis Kanavos | //Download operations take a long time therefore they have no timeout. |
761 | 9c4346c9 | Panagiotis Kanavos | var client = new RestClient(_baseClient) { Timeout = 0 }; |
762 | cfed7823 | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
763 | cfed7823 | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
764 | cfed7823 | Panagiotis Kanavos | |
765 | cfed7823 | Panagiotis Kanavos | //The container and objectName are relative names. They are joined with the client's |
766 | cfed7823 | Panagiotis Kanavos | //BaseAddress to create the object's absolute address |
767 | cfed7823 | Panagiotis Kanavos | var builder = client.GetAddressBuilder(container, objectName); |
768 | cfed7823 | Panagiotis Kanavos | var uri = builder.Uri; |
769 | cfed7823 | Panagiotis Kanavos | |
770 | 5ce54458 | Panagiotis Kanavos | //Download progress is reported to the Trace log |
771 | 5120f3cb | Panagiotis Kanavos | Log.InfoFormat("[GET] START {0}", objectName); |
772 | 283809f3 | Panagiotis Kanavos | client.DownloadProgressChanged += (sender, args) => |
773 | 5120f3cb | Panagiotis Kanavos | Log.InfoFormat("[GET PROGRESS] {0} {1}% {2} of {3}", |
774 | 283809f3 | Panagiotis Kanavos | fileName, args.ProgressPercentage, |
775 | 283809f3 | Panagiotis Kanavos | args.BytesReceived, |
776 | 5ce54458 | Panagiotis Kanavos | args.TotalBytesToReceive); |
777 | 5ce54458 | Panagiotis Kanavos | |
778 | 5ce54458 | Panagiotis Kanavos | |
779 | 5ce54458 | Panagiotis Kanavos | //Start downloading the object asynchronously |
780 | 5ce54458 | Panagiotis Kanavos | var downloadTask = client.DownloadFileTask(uri, fileName); |
781 | 283809f3 | Panagiotis Kanavos | |
782 | 5ce54458 | Panagiotis Kanavos | //Once the download completes |
783 | 5ce54458 | Panagiotis Kanavos | return downloadTask.ContinueWith(download => |
784 | 283809f3 | Panagiotis Kanavos | { |
785 | 5ce54458 | Panagiotis Kanavos | //Delete the local client object |
786 | 283809f3 | Panagiotis Kanavos | client.Dispose(); |
787 | 5ce54458 | Panagiotis Kanavos | //And report failure or completion |
788 | 283809f3 | Panagiotis Kanavos | if (download.IsFaulted) |
789 | 283809f3 | Panagiotis Kanavos | { |
790 | 5120f3cb | Panagiotis Kanavos | Log.ErrorFormat("[GET] FAIL for {0} with \r{1}", objectName, |
791 | 283809f3 | Panagiotis Kanavos | download.Exception); |
792 | 283809f3 | Panagiotis Kanavos | } |
793 | 283809f3 | Panagiotis Kanavos | else |
794 | 283809f3 | Panagiotis Kanavos | { |
795 | 5120f3cb | Panagiotis Kanavos | Log.InfoFormat("[GET] END {0}", objectName); |
796 | 283809f3 | Panagiotis Kanavos | } |
797 | 283809f3 | Panagiotis Kanavos | }); |
798 | 283809f3 | Panagiotis Kanavos | } |
799 | 283809f3 | Panagiotis Kanavos | catch (Exception exc) |
800 | d78cbf09 | Panagiotis Kanavos | { |
801 | 5120f3cb | Panagiotis Kanavos | Log.ErrorFormat("[GET] END {0} with {1}", objectName, exc); |
802 | 283809f3 | Panagiotis Kanavos | throw; |
803 | d78cbf09 | Panagiotis Kanavos | } |
804 | 283809f3 | Panagiotis Kanavos | |
805 | 283809f3 | Panagiotis Kanavos | |
806 | 283809f3 | Panagiotis Kanavos | |
807 | d78cbf09 | Panagiotis Kanavos | } |
808 | d78cbf09 | Panagiotis Kanavos | |
809 | cfed7823 | Panagiotis Kanavos | public Task<IList<string>> PutHashMap(string account, string container, string objectName, TreeHash hash) |
810 | 5ce54458 | Panagiotis Kanavos | { |
811 | 5ce54458 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
812 | 5ce54458 | Panagiotis Kanavos | throw new ArgumentNullException("container"); |
813 | 5ce54458 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(objectName)) |
814 | 5ce54458 | Panagiotis Kanavos | throw new ArgumentNullException("objectName"); |
815 | 5ce54458 | Panagiotis Kanavos | if (hash==null) |
816 | 5ce54458 | Panagiotis Kanavos | throw new ArgumentNullException("hash"); |
817 | 5ce54458 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(Token)) |
818 | 5ce54458 | Panagiotis Kanavos | throw new InvalidOperationException("Invalid Token"); |
819 | 5ce54458 | Panagiotis Kanavos | if (StorageUrl == null) |
820 | 5ce54458 | Panagiotis Kanavos | throw new InvalidOperationException("Invalid Storage Url"); |
821 | 5ce54458 | Panagiotis Kanavos | Contract.EndContractBlock(); |
822 | cfed7823 | Panagiotis Kanavos | |
823 | cfed7823 | Panagiotis Kanavos | |
824 | cfed7823 | Panagiotis Kanavos | //Don't use a timeout because putting the hashmap may be a long process |
825 | cfed7823 | Panagiotis Kanavos | var client = new RestClient(_baseClient) { Timeout = 0 }; |
826 | cfed7823 | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
827 | cfed7823 | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
828 | cfed7823 | Panagiotis Kanavos | |
829 | 5ce54458 | Panagiotis Kanavos | //The container and objectName are relative names. They are joined with the client's |
830 | 5ce54458 | Panagiotis Kanavos | //BaseAddress to create the object's absolute address |
831 | cfed7823 | Panagiotis Kanavos | var builder = client.GetAddressBuilder(container, objectName); |
832 | 5ce54458 | Panagiotis Kanavos | builder.Query = "format=json&hashmap"; |
833 | 5ce54458 | Panagiotis Kanavos | var uri = builder.Uri; |
834 | 5ce54458 | Panagiotis Kanavos | |
835 | 5ce54458 | Panagiotis Kanavos | |
836 | 5ce54458 | Panagiotis Kanavos | //Send the tree hash as Json to the server |
837 | 5ce54458 | Panagiotis Kanavos | client.Headers[HttpRequestHeader.ContentType] = "application/octet-stream"; |
838 | 5ce54458 | Panagiotis Kanavos | var uploadTask=client.UploadStringTask(uri, "PUT", hash.ToJson()); |
839 | 5ce54458 | Panagiotis Kanavos | |
840 | 5ce54458 | Panagiotis Kanavos | |
841 | 5ce54458 | Panagiotis Kanavos | return uploadTask.ContinueWith(t => |
842 | 5ce54458 | Panagiotis Kanavos | { |
843 | a27aa447 | Panagiotis Kanavos | |
844 | a27aa447 | Panagiotis Kanavos | var empty = (IList<string>)new List<string>(); |
845 | 5ce54458 | Panagiotis Kanavos | |
846 | 5ce54458 | Panagiotis Kanavos | |
847 | 5ce54458 | Panagiotis Kanavos | //The server will respond either with 201-created if all blocks were already on the server |
848 | a27aa447 | Panagiotis Kanavos | if (client.StatusCode == HttpStatusCode.Created) |
849 | a27aa447 | Panagiotis Kanavos | { |
850 | 5ce54458 | Panagiotis Kanavos | //in which case we return an empty hash list |
851 | a27aa447 | Panagiotis Kanavos | return empty; |
852 | a27aa447 | Panagiotis Kanavos | } |
853 | 5ce54458 | Panagiotis Kanavos | //or with a 409-conflict and return the list of missing parts |
854 | 5ce54458 | Panagiotis Kanavos | //A 409 will cause an exception so we need to check t.IsFaulted to avoid propagating the exception |
855 | 5ce54458 | Panagiotis Kanavos | if (t.IsFaulted) |
856 | 5ce54458 | Panagiotis Kanavos | { |
857 | 5ce54458 | Panagiotis Kanavos | var ex = t.Exception.InnerException; |
858 | 5ce54458 | Panagiotis Kanavos | var we = ex as WebException; |
859 | 5ce54458 | Panagiotis Kanavos | var response = we.Response as HttpWebResponse; |
860 | 5ce54458 | Panagiotis Kanavos | if (response!=null && response.StatusCode==HttpStatusCode.Conflict) |
861 | 5ce54458 | Panagiotis Kanavos | { |
862 | 5ce54458 | Panagiotis Kanavos | //In case of 409 the missing parts will be in the response content |
863 | 5ce54458 | Panagiotis Kanavos | using (var stream = response.GetResponseStream()) |
864 | 5ce54458 | Panagiotis Kanavos | using(var reader=new StreamReader(stream)) |
865 | 5ce54458 | Panagiotis Kanavos | { |
866 | a27aa447 | Panagiotis Kanavos | //We need to cleanup the content before returning it because it contains |
867 | a27aa447 | Panagiotis Kanavos | //error content after the list of hashes |
868 | a27aa447 | Panagiotis Kanavos | var hashes = new List<string>(); |
869 | a27aa447 | Panagiotis Kanavos | string line=null; |
870 | a27aa447 | Panagiotis Kanavos | //All lines up to the first empty line are hashes |
871 | a27aa447 | Panagiotis Kanavos | while(!String.IsNullOrWhiteSpace(line=reader.ReadLine())) |
872 | a27aa447 | Panagiotis Kanavos | { |
873 | a27aa447 | Panagiotis Kanavos | hashes.Add(line); |
874 | a27aa447 | Panagiotis Kanavos | } |
875 | a27aa447 | Panagiotis Kanavos | |
876 | a27aa447 | Panagiotis Kanavos | return hashes; |
877 | 5ce54458 | Panagiotis Kanavos | } |
878 | 5ce54458 | Panagiotis Kanavos | } |
879 | 5ce54458 | Panagiotis Kanavos | else |
880 | 5ce54458 | Panagiotis Kanavos | //Any other status code is unexpected and the exception should be rethrown |
881 | 5ce54458 | Panagiotis Kanavos | throw ex; |
882 | 5ce54458 | Panagiotis Kanavos | |
883 | 5ce54458 | Panagiotis Kanavos | } |
884 | 5ce54458 | Panagiotis Kanavos | //Any other status code is unexpected but there was no exception. We can probably continue processing |
885 | 5ce54458 | Panagiotis Kanavos | else |
886 | 5ce54458 | Panagiotis Kanavos | { |
887 | 5120f3cb | Panagiotis Kanavos | Log.WarnFormat("Unexcpected status code when putting map: {0} - {1}",client.StatusCode,client.StatusDescription); |
888 | 5ce54458 | Panagiotis Kanavos | } |
889 | a27aa447 | Panagiotis Kanavos | return empty; |
890 | 5ce54458 | Panagiotis Kanavos | }); |
891 | 5ce54458 | Panagiotis Kanavos | |
892 | 5ce54458 | Panagiotis Kanavos | } |
893 | 5ce54458 | Panagiotis Kanavos | |
894 | cfed7823 | Panagiotis Kanavos | public Task<byte[]> GetBlock(string account, string container, Uri relativeUrl, long start, long? end) |
895 | a27aa447 | Panagiotis Kanavos | { |
896 | a27aa447 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(Token)) |
897 | a27aa447 | Panagiotis Kanavos | throw new InvalidOperationException("Invalid Token"); |
898 | a27aa447 | Panagiotis Kanavos | if (StorageUrl == null) |
899 | a27aa447 | Panagiotis Kanavos | throw new InvalidOperationException("Invalid Storage Url"); |
900 | a27aa447 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
901 | a27aa447 | Panagiotis Kanavos | throw new ArgumentNullException("container"); |
902 | a27aa447 | Panagiotis Kanavos | if (relativeUrl== null) |
903 | a27aa447 | Panagiotis Kanavos | throw new ArgumentNullException("relativeUrl"); |
904 | a27aa447 | Panagiotis Kanavos | if (end.HasValue && end<0) |
905 | a27aa447 | Panagiotis Kanavos | throw new ArgumentOutOfRangeException("end"); |
906 | a27aa447 | Panagiotis Kanavos | if (start<0) |
907 | a27aa447 | Panagiotis Kanavos | throw new ArgumentOutOfRangeException("start"); |
908 | a27aa447 | Panagiotis Kanavos | Contract.EndContractBlock(); |
909 | a27aa447 | Panagiotis Kanavos | |
910 | a27aa447 | Panagiotis Kanavos | |
911 | a27aa447 | Panagiotis Kanavos | //Don't use a timeout because putting the hashmap may be a long process |
912 | a27aa447 | Panagiotis Kanavos | var client = new RestClient(_baseClient) {Timeout = 0, RangeFrom = start, RangeTo = end}; |
913 | cfed7823 | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
914 | cfed7823 | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
915 | cfed7823 | Panagiotis Kanavos | |
916 | cfed7823 | Panagiotis Kanavos | var builder = client.GetAddressBuilder(container, relativeUrl.ToString()); |
917 | cfed7823 | Panagiotis Kanavos | var uri = builder.Uri; |
918 | cfed7823 | Panagiotis Kanavos | |
919 | a27aa447 | Panagiotis Kanavos | return client.DownloadDataTask(uri) |
920 | a27aa447 | Panagiotis Kanavos | .ContinueWith(t=> |
921 | a27aa447 | Panagiotis Kanavos | { |
922 | a27aa447 | Panagiotis Kanavos | client.Dispose(); |
923 | a27aa447 | Panagiotis Kanavos | return t.Result; |
924 | a27aa447 | Panagiotis Kanavos | }); |
925 | a27aa447 | Panagiotis Kanavos | } |
926 | a27aa447 | Panagiotis Kanavos | |
927 | a27aa447 | Panagiotis Kanavos | |
928 | cfed7823 | Panagiotis Kanavos | public Task PostBlock(string account, string container, byte[] block, int offset, int count) |
929 | a27aa447 | Panagiotis Kanavos | { |
930 | a27aa447 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
931 | a27aa447 | Panagiotis Kanavos | throw new ArgumentNullException("container"); |
932 | a27aa447 | Panagiotis Kanavos | if (block == null) |
933 | a27aa447 | Panagiotis Kanavos | throw new ArgumentNullException("block"); |
934 | 0af3141d | Panagiotis Kanavos | if (offset < 0 || offset >= block.Length) |
935 | 0af3141d | Panagiotis Kanavos | throw new ArgumentOutOfRangeException("offset"); |
936 | 0af3141d | Panagiotis Kanavos | if (count < 0 || count > block.Length) |
937 | 0af3141d | Panagiotis Kanavos | throw new ArgumentOutOfRangeException("count"); |
938 | a27aa447 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(Token)) |
939 | a27aa447 | Panagiotis Kanavos | throw new InvalidOperationException("Invalid Token"); |
940 | a27aa447 | Panagiotis Kanavos | if (StorageUrl == null) |
941 | 0af3141d | Panagiotis Kanavos | throw new InvalidOperationException("Invalid Storage Url"); |
942 | a27aa447 | Panagiotis Kanavos | Contract.EndContractBlock(); |
943 | a27aa447 | Panagiotis Kanavos | |
944 | cfed7823 | Panagiotis Kanavos | |
945 | cfed7823 | Panagiotis Kanavos | //Don't use a timeout because putting the hashmap may be a long process |
946 | cfed7823 | Panagiotis Kanavos | var client = new RestClient(_baseClient) { Timeout = 0 }; |
947 | cfed7823 | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
948 | cfed7823 | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
949 | cfed7823 | Panagiotis Kanavos | |
950 | cfed7823 | Panagiotis Kanavos | var builder = client.GetAddressBuilder(container, ""); |
951 | a27aa447 | Panagiotis Kanavos | //We are doing an update |
952 | a27aa447 | Panagiotis Kanavos | builder.Query = "update"; |
953 | a27aa447 | Panagiotis Kanavos | var uri = builder.Uri; |
954 | cfed7823 | Panagiotis Kanavos | |
955 | a27aa447 | Panagiotis Kanavos | client.Headers[HttpRequestHeader.ContentType] = "application/octet-stream"; |
956 | a27aa447 | Panagiotis Kanavos | |
957 | 5120f3cb | Panagiotis Kanavos | Log.InfoFormat("[BLOCK POST] START"); |
958 | a27aa447 | Panagiotis Kanavos | |
959 | a64c87c8 | Panagiotis Kanavos | client.UploadProgressChanged += (sender, args) => |
960 | 5120f3cb | Panagiotis Kanavos | Log.InfoFormat("[BLOCK POST PROGRESS] {0}% {1} of {2}", |
961 | a64c87c8 | Panagiotis Kanavos | args.ProgressPercentage, args.BytesSent, |
962 | a64c87c8 | Panagiotis Kanavos | args.TotalBytesToSend); |
963 | a64c87c8 | Panagiotis Kanavos | client.UploadFileCompleted += (sender, args) => |
964 | 5120f3cb | Panagiotis Kanavos | Log.InfoFormat("[BLOCK POST PROGRESS] Completed "); |
965 | a27aa447 | Panagiotis Kanavos | |
966 | a64c87c8 | Panagiotis Kanavos | |
967 | a64c87c8 | Panagiotis Kanavos | //Send the block |
968 | a64c87c8 | Panagiotis Kanavos | var uploadTask = client.UploadDataTask(uri, "POST", block) |
969 | a64c87c8 | Panagiotis Kanavos | .ContinueWith(upload => |
970 | a27aa447 | Panagiotis Kanavos | { |
971 | a64c87c8 | Panagiotis Kanavos | client.Dispose(); |
972 | a27aa447 | Panagiotis Kanavos | |
973 | a64c87c8 | Panagiotis Kanavos | if (upload.IsFaulted) |
974 | a27aa447 | Panagiotis Kanavos | { |
975 | a64c87c8 | Panagiotis Kanavos | var exception = upload.Exception.InnerException; |
976 | 5120f3cb | Panagiotis Kanavos | Log.ErrorFormat("[BLOCK POST] FAIL with \r{0}", exception); |
977 | a64c87c8 | Panagiotis Kanavos | throw exception; |
978 | a64c87c8 | Panagiotis Kanavos | } |
979 | a64c87c8 | Panagiotis Kanavos | |
980 | 5120f3cb | Panagiotis Kanavos | Log.InfoFormat("[BLOCK POST] END"); |
981 | a64c87c8 | Panagiotis Kanavos | }); |
982 | a27aa447 | Panagiotis Kanavos | return uploadTask; |
983 | a27aa447 | Panagiotis Kanavos | } |
984 | a27aa447 | Panagiotis Kanavos | |
985 | 5ce54458 | Panagiotis Kanavos | |
986 | cfed7823 | Panagiotis Kanavos | public Task<TreeHash> GetHashMap(string account, string container, string objectName) |
987 | 5ce54458 | Panagiotis Kanavos | { |
988 | 5ce54458 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
989 | 5ce54458 | Panagiotis Kanavos | throw new ArgumentNullException("container"); |
990 | 5ce54458 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(objectName)) |
991 | 5ce54458 | Panagiotis Kanavos | throw new ArgumentNullException("objectName"); |
992 | 5ce54458 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(Token)) |
993 | 5ce54458 | Panagiotis Kanavos | throw new InvalidOperationException("Invalid Token"); |
994 | 5ce54458 | Panagiotis Kanavos | if (StorageUrl == null) |
995 | 5ce54458 | Panagiotis Kanavos | throw new InvalidOperationException("Invalid Storage Url"); |
996 | 5ce54458 | Panagiotis Kanavos | Contract.EndContractBlock(); |
997 | 5ce54458 | Panagiotis Kanavos | |
998 | 5ce54458 | Panagiotis Kanavos | try |
999 | 5ce54458 | Panagiotis Kanavos | { |
1000 | 5ce54458 | Panagiotis Kanavos | //WebClient, and by extension RestClient, are not thread-safe. Create a new RestClient |
1001 | 5ce54458 | Panagiotis Kanavos | //object to avoid concurrency errors. |
1002 | 5ce54458 | Panagiotis Kanavos | // |
1003 | 5ce54458 | Panagiotis Kanavos | //Download operations take a long time therefore they have no timeout. |
1004 | 5ce54458 | Panagiotis Kanavos | //TODO: Do we really? this is a hashmap operation, not a download |
1005 | 5ce54458 | Panagiotis Kanavos | var client = new RestClient(_baseClient) { Timeout = 0 }; |
1006 | cfed7823 | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
1007 | cfed7823 | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
1008 | cfed7823 | Panagiotis Kanavos | |
1009 | 5ce54458 | Panagiotis Kanavos | |
1010 | cfed7823 | Panagiotis Kanavos | //The container and objectName are relative names. They are joined with the client's |
1011 | cfed7823 | Panagiotis Kanavos | //BaseAddress to create the object's absolute address |
1012 | cfed7823 | Panagiotis Kanavos | var builder = client.GetAddressBuilder(container, objectName); |
1013 | cfed7823 | Panagiotis Kanavos | builder.Query = "format=json&hashmap"; |
1014 | cfed7823 | Panagiotis Kanavos | var uri = builder.Uri; |
1015 | cfed7823 | Panagiotis Kanavos | |
1016 | 5ce54458 | Panagiotis Kanavos | //Start downloading the object asynchronously |
1017 | 5ce54458 | Panagiotis Kanavos | var downloadTask = client.DownloadStringTask(uri); |
1018 | 5ce54458 | Panagiotis Kanavos | |
1019 | 5ce54458 | Panagiotis Kanavos | //Once the download completes |
1020 | 5ce54458 | Panagiotis Kanavos | return downloadTask.ContinueWith(download => |
1021 | 5ce54458 | Panagiotis Kanavos | { |
1022 | 5ce54458 | Panagiotis Kanavos | //Delete the local client object |
1023 | 5ce54458 | Panagiotis Kanavos | client.Dispose(); |
1024 | 5ce54458 | Panagiotis Kanavos | //And report failure or completion |
1025 | 5ce54458 | Panagiotis Kanavos | if (download.IsFaulted) |
1026 | 5ce54458 | Panagiotis Kanavos | { |
1027 | 5120f3cb | Panagiotis Kanavos | Log.ErrorFormat("[GET HASH] FAIL for {0} with \r{1}", objectName, |
1028 | 5ce54458 | Panagiotis Kanavos | download.Exception); |
1029 | 5ce54458 | Panagiotis Kanavos | throw download.Exception; |
1030 | 5ce54458 | Panagiotis Kanavos | } |
1031 | 5ce54458 | Panagiotis Kanavos | |
1032 | 5ce54458 | Panagiotis Kanavos | //The server will return an empty string if the file is empty |
1033 | 5ce54458 | Panagiotis Kanavos | var json = download.Result; |
1034 | 5ce54458 | Panagiotis Kanavos | var treeHash = TreeHash.Parse(json); |
1035 | 5120f3cb | Panagiotis Kanavos | Log.InfoFormat("[GET HASH] END {0}", objectName); |
1036 | 5ce54458 | Panagiotis Kanavos | return treeHash; |
1037 | 5ce54458 | Panagiotis Kanavos | }); |
1038 | 5ce54458 | Panagiotis Kanavos | } |
1039 | 5ce54458 | Panagiotis Kanavos | catch (Exception exc) |
1040 | 5ce54458 | Panagiotis Kanavos | { |
1041 | 5120f3cb | Panagiotis Kanavos | Log.ErrorFormat("[GET HASH] END {0} with {1}", objectName, exc); |
1042 | 5ce54458 | Panagiotis Kanavos | throw; |
1043 | 5ce54458 | Panagiotis Kanavos | } |
1044 | 5ce54458 | Panagiotis Kanavos | |
1045 | 5ce54458 | Panagiotis Kanavos | |
1046 | 5ce54458 | Panagiotis Kanavos | |
1047 | 5ce54458 | Panagiotis Kanavos | } |
1048 | 5ce54458 | Panagiotis Kanavos | |
1049 | 5ce54458 | Panagiotis Kanavos | |
1050 | 5bcf6d70 | Panagiotis Kanavos | /// <summary> |
1051 | 5bcf6d70 | Panagiotis Kanavos | /// |
1052 | 5bcf6d70 | Panagiotis Kanavos | /// </summary> |
1053 | cfed7823 | Panagiotis Kanavos | /// <param name="account"></param> |
1054 | 5bcf6d70 | Panagiotis Kanavos | /// <param name="container"></param> |
1055 | 5bcf6d70 | Panagiotis Kanavos | /// <param name="objectName"></param> |
1056 | 5bcf6d70 | Panagiotis Kanavos | /// <param name="fileName"></param> |
1057 | b5061ac8 | Panagiotis Kanavos | /// <param name="hash">Optional hash value for the file. If no hash is provided, the method calculates a new hash</param> |
1058 | 5bcf6d70 | Panagiotis Kanavos | /// <remarks>>This method should have no timeout or a very long one</remarks> |
1059 | cfed7823 | Panagiotis Kanavos | public Task PutObject(string account, string container, string objectName, string fileName, string hash = null) |
1060 | d78cbf09 | Panagiotis Kanavos | { |
1061 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(container)) |
1062 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("container", "The container property can't be empty"); |
1063 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(objectName)) |
1064 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("objectName", "The objectName property can't be empty"); |
1065 | b6c72f62 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(fileName)) |
1066 | b6c72f62 | Panagiotis Kanavos | throw new ArgumentNullException("fileName", "The fileName property can't be empty"); |
1067 | 637bc368 | Panagiotis Kanavos | if (!File.Exists(fileName)) |
1068 | 637bc368 | Panagiotis Kanavos | throw new FileNotFoundException("The file does not exist",fileName); |
1069 | cfed7823 | Panagiotis Kanavos | Contract.EndContractBlock(); |
1070 | b6c72f62 | Panagiotis Kanavos | |
1071 | b5061ac8 | Panagiotis Kanavos | try |
1072 | b5061ac8 | Panagiotis Kanavos | { |
1073 | cfed7823 | Panagiotis Kanavos | |
1074 | cfed7823 | Panagiotis Kanavos | var client = new RestClient(_baseClient){Timeout=0}; |
1075 | cfed7823 | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
1076 | cfed7823 | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
1077 | cfed7823 | Panagiotis Kanavos | |
1078 | cfed7823 | Panagiotis Kanavos | var builder = client.GetAddressBuilder(container, objectName); |
1079 | 5ce54458 | Panagiotis Kanavos | var uri = builder.Uri; |
1080 | 0eea575a | Panagiotis Kanavos | |
1081 | 0eea575a | Panagiotis Kanavos | string etag = hash ?? CalculateHash(fileName); |
1082 | 0eea575a | Panagiotis Kanavos | |
1083 | 0eea575a | Panagiotis Kanavos | client.Headers.Add("Content-Type", "application/octet-stream"); |
1084 | 0eea575a | Panagiotis Kanavos | client.Headers.Add("ETag", etag); |
1085 | 0eea575a | Panagiotis Kanavos | |
1086 | 0eea575a | Panagiotis Kanavos | |
1087 | 5120f3cb | Panagiotis Kanavos | Log.InfoFormat("[PUT] START {0}", objectName); |
1088 | 0eea575a | Panagiotis Kanavos | client.UploadProgressChanged += (sender, args) => |
1089 | 0eea575a | Panagiotis Kanavos | { |
1090 | 5120f3cb | Panagiotis Kanavos | using (log4net.ThreadContext.Stacks["PUT"].Push("Progress")) |
1091 | 5120f3cb | Panagiotis Kanavos | { |
1092 | 5120f3cb | Panagiotis Kanavos | Log.InfoFormat("{0} {1}% {2} of {3}", fileName, args.ProgressPercentage, |
1093 | 5120f3cb | Panagiotis Kanavos | args.BytesSent, args.TotalBytesToSend); |
1094 | 5120f3cb | Panagiotis Kanavos | } |
1095 | 0eea575a | Panagiotis Kanavos | }; |
1096 | bfc13ed8 | Panagiotis Kanavos | |
1097 | bfc13ed8 | Panagiotis Kanavos | client.UploadFileCompleted += (sender, args) => |
1098 | bfc13ed8 | Panagiotis Kanavos | { |
1099 | 5120f3cb | Panagiotis Kanavos | using (log4net.ThreadContext.Stacks["PUT"].Push("Progress")) |
1100 | 5120f3cb | Panagiotis Kanavos | { |
1101 | 5120f3cb | Panagiotis Kanavos | Log.InfoFormat("Completed {0}", fileName); |
1102 | 5120f3cb | Panagiotis Kanavos | } |
1103 | bfc13ed8 | Panagiotis Kanavos | }; |
1104 | 0eea575a | Panagiotis Kanavos | return client.UploadFileTask(uri, "PUT", fileName) |
1105 | 0eea575a | Panagiotis Kanavos | .ContinueWith(upload=> |
1106 | 0eea575a | Panagiotis Kanavos | { |
1107 | 0eea575a | Panagiotis Kanavos | client.Dispose(); |
1108 | 0eea575a | Panagiotis Kanavos | |
1109 | 0eea575a | Panagiotis Kanavos | if (upload.IsFaulted) |
1110 | a27aa447 | Panagiotis Kanavos | { |
1111 | a27aa447 | Panagiotis Kanavos | var exc = upload.Exception.InnerException; |
1112 | 5120f3cb | Panagiotis Kanavos | Log.ErrorFormat("[PUT] FAIL for {0} with \r{1}",objectName,exc); |
1113 | a27aa447 | Panagiotis Kanavos | throw exc; |
1114 | 0eea575a | Panagiotis Kanavos | } |
1115 | 0eea575a | Panagiotis Kanavos | else |
1116 | 5120f3cb | Panagiotis Kanavos | Log.InfoFormat("[PUT] END {0}", objectName); |
1117 | 0eea575a | Panagiotis Kanavos | }); |
1118 | b5061ac8 | Panagiotis Kanavos | } |
1119 | b5061ac8 | Panagiotis Kanavos | catch (Exception exc) |
1120 | b5061ac8 | Panagiotis Kanavos | { |
1121 | 5120f3cb | Panagiotis Kanavos | Log.ErrorFormat("[PUT] END {0} with {1}", objectName, exc); |
1122 | b5061ac8 | Panagiotis Kanavos | throw; |
1123 | b5061ac8 | Panagiotis Kanavos | } |
1124 | b5061ac8 | Panagiotis Kanavos | |
1125 | 0eea575a | Panagiotis Kanavos | } |
1126 | 0050438e | Panagiotis Kanavos | |
1127 | 4d301e8e | Panagiotis Kanavos | |
1128 | b6c72f62 | Panagiotis Kanavos | private static string CalculateHash(string fileName) |
1129 | d78cbf09 | Panagiotis Kanavos | { |
1130 | 0bd56b7c | Panagiotis Kanavos | Contract.Requires(!String.IsNullOrWhiteSpace(fileName)); |
1131 | 0bd56b7c | Panagiotis Kanavos | Contract.EndContractBlock(); |
1132 | 0bd56b7c | Panagiotis Kanavos | |
1133 | d78cbf09 | Panagiotis Kanavos | string hash; |
1134 | d78cbf09 | Panagiotis Kanavos | using (var hasher = MD5.Create()) |
1135 | b6c72f62 | Panagiotis Kanavos | using(var stream=File.OpenRead(fileName)) |
1136 | d78cbf09 | Panagiotis Kanavos | { |
1137 | d78cbf09 | Panagiotis Kanavos | var hashBuilder=new StringBuilder(); |
1138 | b6c72f62 | Panagiotis Kanavos | foreach (byte b in hasher.ComputeHash(stream)) |
1139 | d78cbf09 | Panagiotis Kanavos | hashBuilder.Append(b.ToString("x2").ToLower()); |
1140 | d78cbf09 | Panagiotis Kanavos | hash = hashBuilder.ToString(); |
1141 | d78cbf09 | Panagiotis Kanavos | } |
1142 | d78cbf09 | Panagiotis Kanavos | return hash; |
1143 | d78cbf09 | Panagiotis Kanavos | } |
1144 | 0bd56b7c | Panagiotis Kanavos | |
1145 | cfed7823 | Panagiotis Kanavos | public void MoveObject(string account, string sourceContainer, string oldObjectName, string targetContainer, string newObjectName) |
1146 | d78cbf09 | Panagiotis Kanavos | { |
1147 | 3c43ec9b | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(sourceContainer)) |
1148 | 3c43ec9b | Panagiotis Kanavos | throw new ArgumentNullException("sourceContainer", "The container property can't be empty"); |
1149 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(oldObjectName)) |
1150 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("oldObjectName", "The oldObjectName property can't be empty"); |
1151 | 3c43ec9b | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(targetContainer)) |
1152 | 3c43ec9b | Panagiotis Kanavos | throw new ArgumentNullException("targetContainer", "The container property can't be empty"); |
1153 | d78cbf09 | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(newObjectName)) |
1154 | d78cbf09 | Panagiotis Kanavos | throw new ArgumentNullException("newObjectName", "The newObjectName property can't be empty"); |
1155 | cfed7823 | Panagiotis Kanavos | Contract.EndContractBlock(); |
1156 | d78cbf09 | Panagiotis Kanavos | |
1157 | 3c43ec9b | Panagiotis Kanavos | var targetUrl = targetContainer + "/" + newObjectName; |
1158 | 3c43ec9b | Panagiotis Kanavos | var sourceUrl = String.Format("/{0}/{1}", sourceContainer, oldObjectName); |
1159 | 3c43ec9b | Panagiotis Kanavos | |
1160 | 9c4346c9 | Panagiotis Kanavos | using (var client = new RestClient(_baseClient)) |
1161 | d78cbf09 | Panagiotis Kanavos | { |
1162 | cfed7823 | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
1163 | cfed7823 | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
1164 | cfed7823 | Panagiotis Kanavos | |
1165 | 0af3141d | Panagiotis Kanavos | client.Headers.Add("X-Move-From", sourceUrl); |
1166 | 9c4346c9 | Panagiotis Kanavos | client.PutWithRetry(targetUrl, 3); |
1167 | 9c4346c9 | Panagiotis Kanavos | |
1168 | 9c4346c9 | Panagiotis Kanavos | var expectedCodes = new[] {HttpStatusCode.OK, HttpStatusCode.NoContent, HttpStatusCode.Created}; |
1169 | 0af3141d | Panagiotis Kanavos | if (!expectedCodes.Contains(client.StatusCode)) |
1170 | 9c4346c9 | Panagiotis Kanavos | throw CreateWebException("MoveObject", client.StatusCode); |
1171 | 9c4346c9 | Panagiotis Kanavos | } |
1172 | d78cbf09 | Panagiotis Kanavos | } |
1173 | d78cbf09 | Panagiotis Kanavos | |
1174 | c53aa229 | Panagiotis Kanavos | public void DeleteObject(string account, string sourceContainer, string objectName) |
1175 | 0af3141d | Panagiotis Kanavos | { |
1176 | 0af3141d | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(sourceContainer)) |
1177 | 0af3141d | Panagiotis Kanavos | throw new ArgumentNullException("sourceContainer", "The container property can't be empty"); |
1178 | 0af3141d | Panagiotis Kanavos | if (String.IsNullOrWhiteSpace(objectName)) |
1179 | 0af3141d | Panagiotis Kanavos | throw new ArgumentNullException("objectName", "The oldObjectName property can't be empty"); |
1180 | cfed7823 | Panagiotis Kanavos | Contract.EndContractBlock(); |
1181 | 0af3141d | Panagiotis Kanavos | |
1182 | c53aa229 | Panagiotis Kanavos | var targetUrl = FolderConstants.TrashContainer + "/" + objectName; |
1183 | 0af3141d | Panagiotis Kanavos | var sourceUrl = String.Format("/{0}/{1}", sourceContainer, objectName); |
1184 | 0af3141d | Panagiotis Kanavos | |
1185 | 0af3141d | Panagiotis Kanavos | using (var client = new RestClient(_baseClient)) |
1186 | 0af3141d | Panagiotis Kanavos | { |
1187 | cfed7823 | Panagiotis Kanavos | if (!String.IsNullOrWhiteSpace(account)) |
1188 | cfed7823 | Panagiotis Kanavos | client.BaseAddress = GetAccountUrl(account); |
1189 | cfed7823 | Panagiotis Kanavos | |
1190 | 0af3141d | Panagiotis Kanavos | client.Headers.Add("X-Move-From", sourceUrl); |
1191 | c53aa229 | Panagiotis Kanavos | client.AllowedStatusCodes.Add(HttpStatusCode.NotFound); |
1192 | 0af3141d | Panagiotis Kanavos | client.PutWithRetry(targetUrl, 3); |
1193 | 0af3141d | Panagiotis Kanavos | |
1194 | 0af3141d | Panagiotis Kanavos | var expectedCodes = new[] {HttpStatusCode.OK, HttpStatusCode.NoContent, HttpStatusCode.Created,HttpStatusCode.NotFound}; |
1195 | 0af3141d | Panagiotis Kanavos | if (!expectedCodes.Contains(client.StatusCode)) |
1196 | 0af3141d | Panagiotis Kanavos | throw CreateWebException("DeleteObject", client.StatusCode); |
1197 | 0af3141d | Panagiotis Kanavos | } |
1198 | 0af3141d | Panagiotis Kanavos | } |
1199 | 0af3141d | Panagiotis Kanavos | |
1200 | 4d301e8e | Panagiotis Kanavos | |
1201 | 3c43ec9b | Panagiotis Kanavos | private static WebException CreateWebException(string operation, HttpStatusCode statusCode) |
1202 | 3c43ec9b | Panagiotis Kanavos | { |
1203 | 3c43ec9b | Panagiotis Kanavos | return new WebException(String.Format("{0} failed with unexpected status code {1}", operation, statusCode)); |
1204 | 3c43ec9b | Panagiotis Kanavos | } |
1205 | 3c43ec9b | Panagiotis Kanavos | |
1206 | d15e99b4 | Panagiotis Kanavos | |
1207 | d78cbf09 | Panagiotis Kanavos | } |
1208 | cfed7823 | Panagiotis Kanavos | |
1209 | cfed7823 | Panagiotis Kanavos | public class ShareAccountInfo |
1210 | cfed7823 | Panagiotis Kanavos | { |
1211 | cfed7823 | Panagiotis Kanavos | public DateTime? last_modified { get; set; } |
1212 | cfed7823 | Panagiotis Kanavos | public string name { get; set; } |
1213 | cfed7823 | Panagiotis Kanavos | } |
1214 | d78cbf09 | Panagiotis Kanavos | } |