var fileAgent = GetFileAgent(accountInfo);
foreach (var trashObject in trashObjects)
{
- var relativePath = trashObject.RelativeUrlToFilePath(accountInfo.UserName);
- //and remove any matching objects from the list, adding them to the commonObjects list
+ var barePath = trashObject.RelativeUrlToFilePath(accountInfo.UserName);
+ //HACK: Assume only the "pithos" container is used. Must find out what happens when
+ //deleting a file from a different container
+ var relativePath = Path.Combine("pithos", barePath);
fileAgent.Delete(relativePath);
}
}
try
{
if (action == null)
- throw new ArgumentNullException("action");
+ throw new ArgumentNullException("action");
Contract.EndContractBlock();
- var accountInfo=action.AccountInfo;
-
- var fileInfo=action.LocalFile;
+ var accountInfo = action.AccountInfo;
+
+ var fileInfo = action.LocalFile;
if (fileInfo.Extension.Equals("ignore", StringComparison.InvariantCultureIgnoreCase))
return;
var relativePath = fileInfo.AsRelativeTo(accountInfo.AccountPath);
if (relativePath.StartsWith(FolderConstants.OthersFolder))
{
- var parts=relativePath.Split('\\');
+ var parts = relativePath.Split('\\');
var accountName = parts[1];
var oldName = accountInfo.UserName;
var absoluteUri = accountInfo.StorageUri.AbsoluteUri;
- var nameIndex=absoluteUri.IndexOf(oldName);
- var root=absoluteUri.Substring(0, nameIndex);
+ var nameIndex = absoluteUri.IndexOf(oldName);
+ var root = absoluteUri.Substring(0, nameIndex);
accountInfo = new AccountInfo
{
UserName = accountName,
AccountPath = Path.Combine(accountInfo.AccountPath, parts[0], parts[1]),
StorageUri = new Uri(root + accountName),
- BlockHash=accountInfo.BlockHash,
- BlockSize=accountInfo.BlockSize,
- Token=accountInfo.Token
+ BlockHash = accountInfo.BlockHash,
+ BlockSize = accountInfo.BlockSize,
+ Token = accountInfo.Token
};
}
var fullFileName = fileInfo.FullName;
- using(var gate=NetworkGate.Acquire(fullFileName,NetworkOperation.Uploading))
+ using (var gate = NetworkGate.Acquire(fullFileName, NetworkOperation.Uploading))
{
//Abort if the file is already being uploaded or downloaded
if (gate.Failed)
var client = new CloudFilesClient(accountInfo);
//Even if GetObjectInfo times out, we can proceed with the upload
- var info = client.GetObjectInfo(account, cloudFile.Container, cloudFile.Name);
+ var info = client.GetObjectInfo(account, cloudFile.Container, cloudFile.Name);
var cloudHash = info.Hash.ToLower();
var hash = action.LocalHash.Value;
var topHash = action.TopHash.Value;
//If the file hashes match, abort the upload
- if (hash == cloudHash || topHash ==cloudHash)
+ if (hash == cloudHash || topHash == cloudHash)
{
//but store any metadata changes
this.StatusKeeper.StoreInfo(fullFileName, info);
return;
}
- if (info.AllowedTo=="read")
+ if (info.AllowedTo == "read")
return;
//Mark the file as modified while we upload it
//First, calculate the tree hash
var treeHash = await Signature.CalculateTreeHashAsync(fileInfo.FullName, accountInfo.BlockSize,
- accountInfo.BlockHash);
-
- await UploadWithHashMap(accountInfo,cloudFile,fileInfo,cloudFile.Name,treeHash);
+ accountInfo.BlockHash);
+
+ await UploadWithHashMap(accountInfo, cloudFile, fileInfo, cloudFile.Name, treeHash);
//If everything succeeds, change the file and overlay status to normal
this.StatusKeeper.SetFileState(fullFileName, FileStatus.Unchanged, FileOverlayStatus.Normal);
var exc = ex.InnerException as WebException;
if (exc == null)
throw ex.InnerException;
- var response = exc.Response as HttpWebResponse;
- if (response == null)
- throw exc;
- if (response.StatusCode == HttpStatusCode.Unauthorized)
- {
- Log.Error("Not allowed to upload file", exc);
- var message = String.Format("Not allowed to uplad file {0}", action.LocalFile.FullName);
- StatusKeeper.SetFileState(action.LocalFile.FullName, FileStatus.Unchanged, FileOverlayStatus.Normal);
- StatusNotification.NotifyChange(message, TraceLevel.Warning);
+ if (HandleUploadWebException(action, exc))
return;
- }
+ throw;
+ }
+ catch (WebException ex)
+ {
+ if (HandleUploadWebException(action, ex))
+ return;
+ throw;
+ }
+ catch (Exception ex)
+ {
+ Log.Error("Unexpected error while uploading file", ex);
throw;
}
}
+ private bool HandleUploadWebException(CloudAction action, WebException exc)
+ {
+ var response = exc.Response as HttpWebResponse;
+ if (response == null)
+ throw exc;
+ if (response.StatusCode == HttpStatusCode.Unauthorized)
+ {
+ Log.Error("Not allowed to upload file", exc);
+ var message = String.Format("Not allowed to uplad file {0}", action.LocalFile.FullName);
+ StatusKeeper.SetFileState(action.LocalFile.FullName, FileStatus.Unchanged, FileOverlayStatus.Normal);
+ StatusNotification.NotifyChange(message, TraceLevel.Warning);
+ return true;
+ }
+ return false;
+ }
+
public async Task UploadWithHashMap(AccountInfo accountInfo,ObjectInfo cloudFile,FileInfo fileInfo,string url,TreeHash treeHash)
{
if (accountInfo == null)
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel.Composition;
+using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq;
//Don't use a timeout because putting the hashmap may be a long process
- var client = new RestClient(_baseClient) { Timeout = 0 };
+ var client = new RestClient(_baseClient) { Timeout = 0 };
if (!String.IsNullOrWhiteSpace(account))
client.BaseAddress = GetAccountUrl(account);
//Send the tree hash as Json to the server
client.Headers[HttpRequestHeader.ContentType] = "application/octet-stream";
- var uploadTask=client.UploadStringTask(uri, "PUT", hash.ToJson());
-
+ var jsonHash = hash.ToJson();
+ var uploadTask=client.UploadStringTask(uri, "PUT", jsonHash);
return uploadTask.ContinueWith(t =>
{
using (var stream = response.GetResponseStream())
using(var reader=new StreamReader(stream))
{
+ Debug.Assert(stream.Position == 0);
//We need to cleanup the content before returning it because it contains
//error content after the list of hashes
var hashes = new List<string>();
}
- private WebHeaderCollection _responseHeaders;
-
- public new WebHeaderCollection ResponseHeaders
- {
- get
- {
- if (base.ResponseHeaders==null)
- {
- return _responseHeaders;
- }
- else
- {
- _responseHeaders = null;
- return base.ResponseHeaders;
- }
-
- }
-
- set { _responseHeaders = value; }
- }
protected override WebRequest GetWebRequest(Uri address)
{
TimedOut = false;
//Does the response have any content to log?
if (exc.Response.ContentLength > 0)
{
- var content = GetContent(exc.Response);
+ var content = LogContent(exc.Response);
Log.ErrorFormat(content);
}
return false;
public DateTime LastModified { get; private set; }
- private static string GetContent(WebResponse webResponse)
+ private static string LogContent(WebResponse webResponse)
{
if (webResponse == null)
throw new ArgumentNullException("webResponse");
Contract.EndContractBlock();
- string content;
- using (var stream = webResponse.GetResponseStream())
- using (var reader = new StreamReader(stream))
+ //The response stream must be copied to avoid affecting other code by disposing of the
+ //original response stream.
+ var stream = webResponse.GetResponseStream();
+ using(var memStream=new MemoryStream((int) stream.Length))
+ using (var reader = new StreamReader(memStream))
{
- content = reader.ReadToEnd();
+ stream.CopyTo(memStream);
+ string content = reader.ReadToEnd();
+
+ stream.Seek(0,SeekOrigin.Begin);
+ return content;
}
- return content;
}
public string DownloadStringWithRetry(string address,int retries=0)
var actualRetries = (retries == 0) ? Retries : retries;
-
+ var uriString = String.Join("/", BaseAddress.TrimEnd('/'), actualAddress);
+
var task = Retry(() =>
- {
- var uriString = String.Join("/", BaseAddress.TrimEnd('/'), actualAddress);
+ {
var content = base.DownloadString(uriString);
if (StatusCode == HttpStatusCode.NoContent)
if (method == "PUT")
request.ContentLength = 0;
+ //Have to use try/finally instead of using here, because WebClient needs a valid WebResponse object
+ //in order to return response headers
var response = (HttpWebResponse)GetWebResponse(request);
- //var response = (HttpWebResponse)request.GetResponse();
+ try
+ {
+ LastModified = response.LastModified;
+ StatusCode = response.StatusCode;
+ StatusDescription = response.StatusDescription;
+ }
+ finally
+ {
+ response.Close();
+ }
- //ResponseHeaders= response.Headers;
-
- LastModified = response.LastModified;
- StatusCode = response.StatusCode;
- StatusDescription = response.StatusDescription;
- response.Close();
return 0;
}, actualRetries);