Exemplo n.º 1
0
        public void StartDownload()
        {
            if (Token == null)
            {
                Token = TransferService.RequestDownloadToken(ResourceId, false);
            }

            while (true)
            {
                IDataBlockInfo blockInfo;
                string         transferId = Token.TransferId;

                long nextBlock = 0;
                if (Token.LastTransmittedBlockInfo != null)
                {
                    nextBlock = Token.LastTransmittedBlockInfo.BlockNumber + 1;
                }

                if (UseStreamingTransfer)
                {
                    StreamedDataBlock block = TransferService.ReadBlockStreamed(transferId, nextBlock);
                    block.Data.WriteTo(OutputStream);
                    blockInfo = block;
                }
                else
                {
                    BufferedDataBlock block = TransferService.ReadBlock(transferId, nextBlock);
                    OutputStream.Write(block.Data, 0, block.Data.Length);
                    blockInfo = block;
                }

                //update the token, get independent file info without data or stream
                Token.LastTransmittedBlockInfo  = DataBlockInfo.FromDataBlock(blockInfo);
                Token.LastBlockTransmissionTime = SystemTime.Now();

                if (blockInfo.IsLastBlock)
                {
                    //we're done - update token data
                    Token.CompletionTime = Token.LastBlockTransmissionTime;
                    TransferService.CompleteTransfer(transferId);
                    Token.Status = TransferStatus.Completed;

                    break;
                }
            }
        }
Exemplo n.º 2
0
 /// <summary>
 /// Adds a <see cref="DataBlockInfo"/> instance to the internal
 /// list of registered data blocks.
 /// </summary>
 /// <param name="dataBlock"></param>
 public void RegisterBlock(DataBlockInfo dataBlock)
 {
     Ensure.ArgumentNotNull(dataBlock, "dataBlock");
     transferredBlocks[dataBlock.BlockNumber] = dataBlock;
 }
Exemplo n.º 3
0
        /// <summary>
        /// Orchestrates common block reading procedures for the <see cref="ReadBlock"/> and
        /// <see cref="ReadBlockStreamed"/> methods.
        /// </summary>
        protected virtual T OrchestrateBlockReading <T>(TTransfer transfer, long blockNumber,
                                                        Func <TTransfer, long, DataBlockInfo, T> readerImplFunc) where T : IDataBlock
        {
            const FileSystemTask context = FileSystemTask.DataBlockDownloadRequest;

            if (blockNumber < 0)
            {
                string msg = "Invalid block number [{0}] requested - block numbers cannot be negative.";
                msg = String.Format(msg, blockNumber);
                throw new DataBlockException(msg);
            }

            if (blockNumber >= transfer.Token.TotalBlockCount)
            {
                string msg = "Invalid block number [{0}] requested - the total number of blocks is [{1}].";
                msg = String.Format(msg, blockNumber, transfer.Token.TotalBlockCount);
                throw new DataBlockException(msg);
            }

            //make sure the file still exists
            if (!transfer.FileItem.Exists)
            {
                Auditor.AuditRequestedFileNotFound(transfer.FileItem, context);

                string msg = "Resource [{0}] of transfer [{1}] was not found.";
                msg = String.Format(msg, transfer.Token.ResourceName, transfer.TransferId);
                throw new VirtualResourceNotFoundException(msg)
                      {
                          IsAudited = true
                      };
            }

            lock (transfer.SyncRoot)
            {
                //make sure the transfer is active
                if (!transfer.Status.Is(TransferStatus.Starting, TransferStatus.Running, TransferStatus.Paused))
                {
                    string msg = String.Format("Transfer [{0}] is not active anymore - status is [{1}].", transfer.TransferId,
                                               transfer.Status);

                    if (transfer.AbortReason.HasValue)
                    {
                        msg += String.Format(" Transfer abort reason: [{0}].", transfer.AbortReason);
                    }

                    Auditor.AuditDeniedOperation(context, AuditEvent.DownloadNoLongerActive, transfer.FileItem, msg);
                    throw new TransferStatusException(msg)
                          {
                              IsAudited = true, EventId = (int)AuditEvent.DownloadNoLongerActive
                          };
                }

                //check whether we already transferred this block once
                DataBlockInfo transferredBlock = transfer.TryGetTransferredBlock(blockNumber);

                T dataBlock = readerImplFunc(transfer, blockNumber, transferredBlock);

                //update status
                transfer.Status = TransferStatus.Running;

                //store copy of the downloaded block that doesn't contain any data
                transfer.RegisterBlock(DataBlockInfo.FromDataBlock(dataBlock));

                //audit download
                Auditor.AuditTransferOperation(context, AuditEvent.FileBlockDownloaded, transfer.TransferId, transfer.FileItem);

                return(dataBlock);
            }
        }
Exemplo n.º 4
0
 /// <summary>
 /// Handles the creation of an actual data block based on the underlying resource.
 /// </summary>
 /// <param name="transfer">The processed transfer.</param>
 /// <param name="blockNumber">The number of the downloaded block.</param>
 /// <param name="previouslyTransferredBlock">If this data block was already transferred, this parameter
 /// contains the information about the block. Can be used in order to ensure proper retransmission in case
 /// of variable block sizes.</param>
 /// <returns>A data block which exposes the data as a resource-friendly stream
 /// (<see cref="BufferedDataBlock.Data"/>).</returns>
 protected abstract StreamedDataBlock CreateStreamedDataBlockImpl(TTransfer transfer, long blockNumber,
                                                                  DataBlockInfo previouslyTransferredBlock);
Exemplo n.º 5
0
        /// <summary>
        /// Handles locking, validation and stream preparation of a given transfer in order to read
        /// a given block of data. The actual reading (either into a buffer, or a returned
        /// stream) is being delegated via the <paramref name="dataReaderFunc"/>.
        /// </summary>
        /// <typeparam name="T">The type of <see cref="IDataBlockInfo"/> that is being returned.</typeparam>
        /// <param name="transferId">The transfer token ID.</param>
        /// <param name="blockNumber">The block number to be read.</param>
        /// <param name="dataReaderFunc">A function that receives the <see cref="DownloadTransfer"/> and
        /// the designated stream offset, and returns the required <see cref="IDataBlockInfo"/> that
        /// provides the block's data.</param>
        /// <returns>The <see cref="IDataBlockInfo"/> that is being created by the <paramref name="dataReaderFunc"/>.</returns>
        private T PrepareBlockReading <T>(string transferId, long blockNumber, Func <DownloadTransfer, long, T> dataReaderFunc) where T : IDataBlockInfo
        {
            DownloadTransfer transfer = GetCachedTransfer(transferId, true);
            DownloadToken    token    = transfer.Token;

            if (!File.Exists(transfer.File.FullName))
            {
                string msg = "Resource [{0}] of transfer [{1}] was not found.";
                msg = String.Format(msg, transfer.Token.ResourceName, transferId);
                throw new VirtualResourceNotFoundException(msg);
            }

            lock (transfer.SyncRoot)
            {
                //make sure the transfer is active
                if (!transfer.Status.Is(TransferStatus.Starting, TransferStatus.Running, TransferStatus.Paused))
                {
                    string msg = String.Format("Transfer is not active anymore - status is [{0}].", transfer.Status);
                    throw new TransferStatusException(msg);
                }

                long position = blockNumber * token.DownloadBlockSize.Value;

                //in case of an invalid position, throw error
                if (position > token.ResourceLength)
                {
                    string msg = "Cannot deliver block {0} - invalid block number.";
                    msg = String.Format(msg, blockNumber);
                    throw new DataBlockException(msg);
                }


                if (transfer.Stream == null)
                {
                    //open stream, share read access
                    transfer.Stream = transfer.File.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
                }

                //reposition stream if necessary
                if (position != transfer.Stream.Position)
                {
                    transfer.Stream.Seek(position, SeekOrigin.Begin);
                }

                T dataBlock = dataReaderFunc(transfer, position);

                if (dataBlock.IsLastBlock)
                {
                    //assume the last block will be processed successfully and
                    //already close the stream (don't wait for the transfer to be
                    //close by client)
                    transfer.Stream.Close();
                    transfer.Stream.Dispose();
                    transfer.Stream = null;
                }

                //update status
                transfer.Token.Status = TransferStatus.Running;

                //maintain local (unshared) copy of the block info without the data
                transfer.Token.LastTransmittedBlockInfo = DataBlockInfo.FromDataBlock(dataBlock);
                return(dataBlock);
            }
        }