commit 6bcdd8e2ecbe77b8774549324d99d86999770556
Author: Panagiotis Kanavos <pkanavos@gmail.com>
Date:   Sat Mar 3 14:49:02 2012 +0200

    Logging improvements

diff --git a/trunk/Pithos.Core/Agents/NetworkAgent.cs b/trunk/Pithos.Core/Agents/NetworkAgent.cs
index 077a810..85c40ad 100644
--- a/trunk/Pithos.Core/Agents/NetworkAgent.cs
+++ b/trunk/Pithos.Core/Agents/NetworkAgent.cs
@@ -115,9 +115,8 @@ namespace Pithos.Core.Agents
 
 
 
-            using (log4net.ThreadContext.Stacks["NETWORK"].Push("PROCESS"))
+            using (log4net.ThreadContext.Stacks["Operation"].Push(action.ToString()))
             {                
-                Log.InfoFormat("[ACTION] Start Processing {0}", action);
 
                 var cloudFile = action.CloudFile;
                 var downloadPath = action.GetDownloadPath();
@@ -125,7 +124,7 @@ namespace Pithos.Core.Agents
                 try
                 {
                     _proceedEvent.Reset();
-                    UpdateStatus(PithosStatus.Syncing);
+                    //UpdateStatus(PithosStatus.Syncing);
                     var accountInfo = action.AccountInfo;
 
                     if (action.Action == CloudActionType.DeleteCloud)
@@ -169,7 +168,7 @@ namespace Pithos.Core.Agents
                                 break;
                         }
                     }
-                    Log.InfoFormat("[ACTION] End Processing {0}:{1}->{2}", action.Action, action.LocalFile,
+                    Log.InfoFormat("End Processing {0}:{1}->{2}", action.Action, action.LocalFile,
                                            action.CloudFile.Name);
                 }
                 catch (WebException exc)
@@ -230,20 +229,22 @@ namespace Pithos.Core.Agents
             if (action.CloudFile == null)
                 throw new ArgumentException("The action's cloud file is not specified", "action");
             Contract.EndContractBlock();
+            using (ThreadContext.Stacks["Operation"].Push("RenameLocalFile"))
+            {
 
-            //We assume that the local file already exists, otherwise the poll agent
-            //would have issued a download request
-
-            var currentInfo = action.CloudFile;
-            var previousInfo = action.CloudFile.Previous;
-            var fileAgent = FileAgent.GetFileAgent(accountInfo);
+                //We assume that the local file already exists, otherwise the poll agent
+                //would have issued a download request
 
-            var previousRelativepath = previousInfo.RelativeUrlToFilePath(accountInfo.UserName);
-            var previousFile = fileAgent.GetFileSystemInfo(previousRelativepath);
+                var currentInfo = action.CloudFile;
+                var previousInfo = action.CloudFile.Previous;
+                var fileAgent = FileAgent.GetFileAgent(accountInfo);
 
-            //In every case we need to move the local file first
-            MoveLocalFile(accountInfo, previousFile, fileAgent, currentInfo);
+                var previousRelativepath = previousInfo.RelativeUrlToFilePath(accountInfo.UserName);
+                var previousFile = fileAgent.GetFileSystemInfo(previousRelativepath);
 
+                //In every case we need to move the local file first
+                MoveLocalFile(accountInfo, previousFile, fileAgent, currentInfo);
+            }
         }
 
         private void MoveLocalFile(AccountInfo accountInfo, FileSystemInfo previousFile, FileAgent fileAgent,
@@ -287,41 +288,44 @@ namespace Pithos.Core.Agents
             if (action.CloudFile== null)
                 throw new ArgumentException("The action's cloud file is not specified", "action");
             Contract.EndContractBlock();
+            using (ThreadContext.Stacks["Operation"].Push("SyncFiles"))
+            {
 
-            var localFile = action.LocalFile;
-            var cloudFile = action.CloudFile;
-            var downloadPath=action.LocalFile.GetProperCapitalization();
+                var localFile = action.LocalFile;
+                var cloudFile = action.CloudFile;
+                var downloadPath = action.LocalFile.GetProperCapitalization();
 
-            var cloudHash = cloudFile.Hash.ToLower();
-            var previousCloudHash = cloudFile.PreviousHash.ToLower();
-            var localHash = action.LocalHash.Value.ToLower();
-            var topHash = action.TopHash.Value.ToLower();
+                var cloudHash = cloudFile.Hash.ToLower();
+                var previousCloudHash = cloudFile.PreviousHash.ToLower();
+                var localHash = action.LocalHash.Value.ToLower();
+                var topHash = action.TopHash.Value.ToLower();
 
-            //At this point we know that an object has changed on the server and that a local
-            //file already exists. We need to decide whether the file has only changed on 
-            //the server or there is a conflicting change on the client.
-            //
-            
-            //Not enough to compare only the local hashes (MD5), also have to compare the tophashes            
-            //If any of the hashes match, we are done
-            if ((cloudHash == localHash || cloudHash == topHash))
-            {
-                Log.InfoFormat("Skipping {0}, hashes match",downloadPath);
-                return;
-            }
+                //At this point we know that an object has changed on the server and that a local
+                //file already exists. We need to decide whether the file has only changed on 
+                //the server or there is a conflicting change on the client.
+                //
 
-            //The hashes DON'T match. We need to sync
+                //Not enough to compare only the local hashes (MD5), also have to compare the tophashes            
+                //If any of the hashes match, we are done
+                if ((cloudHash == localHash || cloudHash == topHash))
+                {
+                    Log.InfoFormat("Skipping {0}, hashes match", downloadPath);
+                    return;
+                }
 
-            // If the previous tophash matches the local tophash, the file was only changed on the server. 
-            if (localHash == previousCloudHash)
-            {
-                await DownloadCloudFile(accountInfo, cloudFile, downloadPath);
-            }
-            else
-            {
-                //If the previous and local hash don't match, there was a local conflict
-                //that was not uploaded to the server. We have a conflict
-                ReportConflict(downloadPath);
+                //The hashes DON'T match. We need to sync
+
+                // If the previous tophash matches the local tophash, the file was only changed on the server. 
+                if (localHash == previousCloudHash)
+                {
+                    await DownloadCloudFile(accountInfo, cloudFile, downloadPath);
+                }
+                else
+                {
+                    //If the previous and local hash don't match, there was a local conflict
+                    //that was not uploaded to the server. We have a conflict
+                    ReportConflict(downloadPath);
+                }
             }
         }
 
@@ -413,36 +417,39 @@ namespace Pithos.Core.Agents
             if (action.OldCloudFile==null)
                 throw new ArgumentException("OldCloudFile","action");
             Contract.EndContractBlock();
-            
-            
-            var newFilePath = action.LocalFile.FullName;
-            
-            //How do we handle concurrent renames and deletes/uploads/downloads?
-            //* A conflicting upload means that a file was renamed before it had a chance to finish uploading
-            //  This should never happen as the network agent executes only one action at a time
-            //* A conflicting download means that the file was modified on the cloud. While we can go on and complete
-            //  the rename, there may be a problem if the file is downloaded in blocks, as subsequent block requests for the 
-            //  same name will fail.
-            //  This should never happen as the network agent executes only one action at a time.
-            //* A conflicting delete can happen if the rename was followed by a delete action that didn't have the chance
-            //  to remove the rename from the queue.
-            //  We can probably ignore this case. It will result in an error which should be ignored            
 
-            
-            //The local file is already renamed
-            StatusKeeper.SetFileOverlayStatus(newFilePath, FileOverlayStatus.Modified);
+            using (ThreadContext.Stacks["Operation"].Push("RenameCloudFile"))
+            {
 
+                var newFilePath = action.LocalFile.FullName;
+
+                //How do we handle concurrent renames and deletes/uploads/downloads?
+                //* A conflicting upload means that a file was renamed before it had a chance to finish uploading
+                //  This should never happen as the network agent executes only one action at a time
+                //* A conflicting download means that the file was modified on the cloud. While we can go on and complete
+                //  the rename, there may be a problem if the file is downloaded in blocks, as subsequent block requests for the 
+                //  same name will fail.
+                //  This should never happen as the network agent executes only one action at a time.
+                //* A conflicting delete can happen if the rename was followed by a delete action that didn't have the chance
+                //  to remove the rename from the queue.
+                //  We can probably ignore this case. It will result in an error which should be ignored            
 
-            var account = action.CloudFile.Account ?? accountInfo.UserName;
-            var container = action.CloudFile.Container;
-            
-            var client = new CloudFilesClient(accountInfo);
-            //TODO: What code is returned when the source file doesn't exist?
-            client.MoveObject(account, container, action.OldCloudFile.Name, container, action.CloudFile.Name);
 
-            StatusKeeper.SetFileStatus(newFilePath, FileStatus.Unchanged);
-            StatusKeeper.SetFileOverlayStatus(newFilePath, FileOverlayStatus.Normal);
-            NativeMethods.RaiseChangeNotification(newFilePath);
+                //The local file is already renamed
+                StatusKeeper.SetFileOverlayStatus(newFilePath, FileOverlayStatus.Modified);
+
+
+                var account = action.CloudFile.Account ?? accountInfo.UserName;
+                var container = action.CloudFile.Container;
+
+                var client = new CloudFilesClient(accountInfo);
+                //TODO: What code is returned when the source file doesn't exist?
+                client.MoveObject(account, container, action.OldCloudFile.Name, container, action.CloudFile.Name);
+
+                StatusKeeper.SetFileStatus(newFilePath, FileStatus.Unchanged);
+                StatusKeeper.SetFileOverlayStatus(newFilePath, FileOverlayStatus.Normal);
+                NativeMethods.RaiseChangeNotification(newFilePath);
+            }
         }
 
         //Download a file.
@@ -461,54 +468,58 @@ namespace Pithos.Core.Agents
             if (!Path.IsPathRooted(filePath))
                 throw new ArgumentException("The filePath must be rooted", "filePath");
             Contract.EndContractBlock();
-            
 
-            var localPath = Interfaces.FileInfoExtensions.GetProperFilePathCapitalization(filePath);
-            var relativeUrl = new Uri(cloudFile.Name, UriKind.Relative);
-
-            var url = relativeUrl.ToString();
-            if (cloudFile.Name.EndsWith(".ignore", StringComparison.InvariantCultureIgnoreCase))
-                return;
+            using (ThreadContext.Stacks["Operation"].Push("DownloadCloudFile"))
+            {
 
+                var localPath = Interfaces.FileInfoExtensions.GetProperFilePathCapitalization(filePath);
+                var relativeUrl = new Uri(cloudFile.Name, UriKind.Relative);
 
-            //Are we already downloading or uploading the file? 
-            using (var gate=NetworkGate.Acquire(localPath, NetworkOperation.Downloading))
-            {
-                if (gate.Failed)
+                var url = relativeUrl.ToString();
+                if (cloudFile.Name.EndsWith(".ignore", StringComparison.InvariantCultureIgnoreCase))
                     return;
-                
-                var client = new CloudFilesClient(accountInfo);
-                var account = cloudFile.Account;
-                var container = cloudFile.Container;
 
-                if (cloudFile.Content_Type == @"application/directory")
+
+                //Are we already downloading or uploading the file? 
+                using (var gate = NetworkGate.Acquire(localPath, NetworkOperation.Downloading))
                 {
-                    if (!Directory.Exists(localPath))
-                        Directory.CreateDirectory(localPath);
-                }
-                else
-                {                    
-                    //Retrieve the hashmap from the server
-                    var serverHash = await client.GetHashMap(account, container, url);
-                    //If it's a small file
-                    if (serverHash.Hashes.Count == 1)
-                        //Download it in one go
-                        await
-                            DownloadEntireFileAsync(accountInfo, client, cloudFile, relativeUrl, localPath, serverHash);
-                        //Otherwise download it block by block
-                    else
-                        await DownloadWithBlocks(accountInfo, client, cloudFile, relativeUrl, localPath, serverHash);
+                    if (gate.Failed)
+                        return;
+
+                    var client = new CloudFilesClient(accountInfo);
+                    var account = cloudFile.Account;
+                    var container = cloudFile.Container;
 
-                    if (cloudFile.AllowedTo == "read")
+                    if (cloudFile.Content_Type == @"application/directory")
                     {
-                        var attributes = File.GetAttributes(localPath);
-                        File.SetAttributes(localPath, attributes | FileAttributes.ReadOnly);                        
+                        if (!Directory.Exists(localPath))
+                            Directory.CreateDirectory(localPath);
+                    }
+                    else
+                    {
+                        //Retrieve the hashmap from the server
+                        var serverHash = await client.GetHashMap(account, container, url);
+                        //If it's a small file
+                        if (serverHash.Hashes.Count == 1)
+                            //Download it in one go
+                            await
+                                DownloadEntireFileAsync(accountInfo, client, cloudFile, relativeUrl, localPath,
+                                                        serverHash);
+                            //Otherwise download it block by block
+                        else
+                            await DownloadWithBlocks(accountInfo, client, cloudFile, relativeUrl, localPath, serverHash);
+
+                        if (cloudFile.AllowedTo == "read")
+                        {
+                            var attributes = File.GetAttributes(localPath);
+                            File.SetAttributes(localPath, attributes | FileAttributes.ReadOnly);
+                        }
                     }
-                }
 
-                //Now we can store the object's metadata without worrying about ghost status entries
-                StatusKeeper.StoreInfo(localPath, cloudFile);
-                
+                    //Now we can store the object's metadata without worrying about ghost status entries
+                    StatusKeeper.StoreInfo(localPath, cloudFile);
+
+                }
             }
         }
 
@@ -604,6 +615,7 @@ namespace Pithos.Core.Agents
             //And compare it with the server's hash
             var upHashes = serverHash.GetHashesAsStrings();
             var localHashes = treeHash.HashDictionary;
+            ReportDownloadProgress(Path.GetFileName(localPath),0,upHashes.Length,cloudFile.Bytes);
             for (int i = 0; i < upHashes.Length; i++)
             {
                 //For every non-matching hash
@@ -633,6 +645,7 @@ namespace Pithos.Core.Agents
 
                     Log.InfoFormat("[BLOCK GET] FINISH {0} of {1} for {2}", i, upHashes.Length, localPath);
                 }
+                ReportDownloadProgress(Path.GetFileName(localPath), i, upHashes.Length, cloudFile.Bytes);
             }
 
             //Want to avoid notifications if no changes were made
@@ -652,123 +665,127 @@ namespace Pithos.Core.Agents
             if (action == null)
                 throw new ArgumentNullException("action");           
             Contract.EndContractBlock();
-
-            try
-            {                
-                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))
+            using(ThreadContext.Stacks["Operation"].Push("UploadCloudFile"))
+            {
+                try
                 {
-                    var parts = relativePath.Split('\\');
-                    var accountName = parts[1];
-                    var oldName = accountInfo.UserName;
-                    var absoluteUri = accountInfo.StorageUri.AbsoluteUri;
-                    var nameIndex = absoluteUri.IndexOf(oldName, StringComparison.Ordinal);
-                    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
-                    };
-                }
+                    var accountInfo = action.AccountInfo;
 
+                    var fileInfo = action.LocalFile;
 
-                var fullFileName = fileInfo.GetProperCapitalization();
-                using (var gate = NetworkGate.Acquire(fullFileName, NetworkOperation.Uploading))
-                {
-                    //Abort if the file is already being uploaded or downloaded
-                    if (gate.Failed)
+                    if (fileInfo.Extension.Equals("ignore", StringComparison.InvariantCultureIgnoreCase))
                         return;
 
-                    var cloudFile = action.CloudFile;
-                    var account = cloudFile.Account ?? accountInfo.UserName;
-
-                    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);
-
-                    //If this is a read-only file, do not upload changes
-                    if (info.AllowedTo == "read")
-                        return;
-                    
-                    //TODO: Check how a directory hash is calculated -> All dirs seem to have the same hash
-                    if (fileInfo is DirectoryInfo)
+                    var relativePath = fileInfo.AsRelativeTo(accountInfo.AccountPath);
+                    if (relativePath.StartsWith(FolderConstants.OthersFolder))
                     {
-                        //If the directory doesn't exist the Hash property will be empty
-                        if (String.IsNullOrWhiteSpace(info.Hash))
-                            //Go on and create the directory
-                            await client.PutObject(account, cloudFile.Container, cloudFile.Name, fullFileName, String.Empty, "application/directory");
+                        var parts = relativePath.Split('\\');
+                        var accountName = parts[1];
+                        var oldName = accountInfo.UserName;
+                        var absoluteUri = accountInfo.StorageUri.AbsoluteUri;
+                        var nameIndex = absoluteUri.IndexOf(oldName, StringComparison.Ordinal);
+                        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
+                                          };
                     }
-                    else
+
+
+                    var fullFileName = fileInfo.GetProperCapitalization();
+                    using (var gate = NetworkGate.Acquire(fullFileName, NetworkOperation.Uploading))
                     {
+                        //Abort if the file is already being uploaded or downloaded
+                        if (gate.Failed)
+                            return;
 
-                        var cloudHash = info.Hash.ToLower();
+                        var cloudFile = action.CloudFile;
+                        var account = cloudFile.Account ?? accountInfo.UserName;
 
-                        var hash = action.LocalHash.Value;
-                        var topHash = action.TopHash.Value;
+                        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);
 
-                        //If the file hashes match, abort the upload
-                        if (hash == cloudHash || topHash == cloudHash)
-                        {
-                            //but store any metadata changes 
-                            StatusKeeper.StoreInfo(fullFileName, info);
-                            Log.InfoFormat("Skip upload of {0}, hashes match", fullFileName);
+                        //If this is a read-only file, do not upload changes
+                        if (info.AllowedTo == "read")
                             return;
+
+                        //TODO: Check how a directory hash is calculated -> All dirs seem to have the same hash
+                        if (fileInfo is DirectoryInfo)
+                        {
+                            //If the directory doesn't exist the Hash property will be empty
+                            if (String.IsNullOrWhiteSpace(info.Hash))
+                                //Go on and create the directory
+                                await
+                                    client.PutObject(account, cloudFile.Container, cloudFile.Name, fullFileName,
+                                                     String.Empty, "application/directory");
                         }
+                        else
+                        {
+
+                            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)
+                            {
+                                //but store any metadata changes 
+                                StatusKeeper.StoreInfo(fullFileName, info);
+                                Log.InfoFormat("Skip upload of {0}, hashes match", fullFileName);
+                                return;
+                            }
 
 
-                        //Mark the file as modified while we upload it
-                        StatusKeeper.SetFileOverlayStatus(fullFileName, FileOverlayStatus.Modified);
-                        //And then upload it
+                            //Mark the file as modified while we upload it
+                            StatusKeeper.SetFileOverlayStatus(fullFileName, FileOverlayStatus.Modified);
+                            //And then upload it
 
-                        //Upload even small files using the Hashmap. The server may already contain
-                        //the relevant block
+                            //Upload even small files using the Hashmap. The server may already contain
+                            //the relevant block
 
-                        //First, calculate the tree hash
-                        var treeHash = await Signature.CalculateTreeHashAsync(fullFileName, accountInfo.BlockSize,
-                                                                              accountInfo.BlockHash, 2);
+                            //First, calculate the tree hash
+                            var treeHash = await Signature.CalculateTreeHashAsync(fullFileName, accountInfo.BlockSize,
+                                                                                  accountInfo.BlockHash, 2);
 
-                        await UploadWithHashMap(accountInfo, cloudFile, fileInfo as FileInfo, cloudFile.Name, treeHash);
+                            await
+                                UploadWithHashMap(accountInfo, cloudFile, fileInfo as FileInfo, cloudFile.Name, treeHash);
+                        }
+                        //If everything succeeds, change the file and overlay status to normal
+                        StatusKeeper.SetFileState(fullFileName, FileStatus.Unchanged, FileOverlayStatus.Normal);
                     }
-                    //If everything succeeds, change the file and overlay status to normal
-                    StatusKeeper.SetFileState(fullFileName, FileStatus.Unchanged, FileOverlayStatus.Normal);
+                    //Notify the Shell to update the overlays
+                    NativeMethods.RaiseChangeNotification(fullFileName);
+                    StatusNotification.NotifyChangedFile(fullFileName);
+                }
+                catch (AggregateException ex)
+                {
+                    var exc = ex.InnerException as WebException;
+                    if (exc == null)
+                        throw ex.InnerException;
+                    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;
                 }
-                //Notify the Shell to update the overlays
-                NativeMethods.RaiseChangeNotification(fullFileName);
-                StatusNotification.NotifyChangedFile(fullFileName);
-            }
-            catch (AggregateException ex)
-            {
-                var exc = ex.InnerException as WebException;
-                if (exc == null)
-                    throw ex.InnerException;
-                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;
             }
-
         }
 
 
@@ -810,9 +827,11 @@ namespace Pithos.Core.Agents
             var account = cloudFile.Account ?? accountInfo.UserName;
             var container = cloudFile.Container ;
 
-            var client = new CloudFilesClient(accountInfo);
+            var client = new CloudFilesClient(accountInfo);            
             //Send the hashmap to the server            
             var missingHashes =  await client.PutHashMap(account, container, url, treeHash);
+            int block = 0;
+            ReportUploadProgress(fileInfo.Name,block++, missingHashes.Count, fileInfo.Length);
             //If the server returns no missing hashes, we are done
             while (missingHashes.Count > 0)
             {
@@ -834,17 +853,25 @@ namespace Pithos.Core.Agents
                     }
                     catch (Exception exc)
                     {
-                        Log.ErrorFormat("[ERROR] uploading block {0} of {1}\n{2}", blockIndex, fullFileName, exc);
+                        Log.Error(String.Format("Uploading block {0} of {1}", blockIndex, fullFileName), exc);
                     }
-
+                    ReportUploadProgress(fileInfo.Name,block++, missingHashes.Count, fileInfo.Length);
                 }
 
                 //Repeat until there are no more missing hashes                
                 missingHashes = await client.PutHashMap(account, container, url, treeHash);
             }
+            ReportUploadProgress(fileInfo.Name, missingHashes.Count, missingHashes.Count, fileInfo.Length);
         }
 
-
+        private void ReportUploadProgress(string fileName,int block, int totalBlocks, long fileSize)
+        {
+            StatusNotification.Notify(new ProgressNotification(fileName,"Uploading",block,totalBlocks,fileSize) );            
+        }
+        private void ReportDownloadProgress(string fileName,int block, int totalBlocks, long fileSize)
+        {
+            StatusNotification.Notify(new ProgressNotification(fileName,"Downloading",block,totalBlocks,fileSize) );            
+        }
     }
 
    
