/// <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); } }
private TTransfer InitTransferImpl(string submittedResourceFilePath, int?clientMaxBlockSize, bool includeFileHash) { const FileSystemTask context = FileSystemTask.DownloadTokenRequest; TFile fileItem = CreateFileItemImpl(submittedResourceFilePath, false, context); if (!fileItem.Exists) { Auditor.AuditRequestedFileNotFound(fileItem, context); string msg = String.Format("Resource [{0}] not found.", submittedResourceFilePath); throw new VirtualResourceNotFoundException(msg) { IsAudited = true }; } //get authorization FileClaims claims = GetFileClaims(fileItem); if (!claims.AllowReadData) { Auditor.AuditDeniedOperation(context, AuditEvent.FileDataDownloadDenied, fileItem); string msg = "Read request for file [{0}] was denied - you are not authorized to read the resource."; msg = String.Format(msg, submittedResourceFilePath); throw new ResourceAccessException(msg) { IsAudited = true }; } //try to get lock ResourceLockGuard readLock = LockResourceForDownload(fileItem, claims); if (readLock != null && !readLock.IsLockEnabled) { Auditor.AuditDeniedOperation(context, AuditEvent.FileReadLockDenied, fileItem); string msg = "The requested file [{0}] is currently locked and thus cannot be accessed."; msg = String.Format(msg, submittedResourceFilePath); throw new ResourceLockedException(msg) { IsAudited = true }; } //create download token DownloadToken token = CreateDownloadToken(submittedResourceFilePath, fileItem, clientMaxBlockSize, includeFileHash); //create expiration job if we have an expiration time Job <DownloadToken> job = null; if (token.ExpirationTime.HasValue) { job = ScheduleExpiration(token); } //create transfer instance TTransfer transfer = CreateTransfer(submittedResourceFilePath, fileItem, token, claims, readLock, job); //cache transfer TransferStore.AddTransfer(transfer); //audit issued token Auditor.AuditResourceOperation(context, AuditEvent.DownloadTokenIssued, fileItem); return(transfer); }