public (Stream stream, DataResponseFaul error) CreateUploadStream(LocalPackageInfo package, int[] requestedSegments) { if (package == null) { throw new ArgumentNullException(nameof(package)); } if (requestedSegments == null) { throw new ArgumentNullException(nameof(requestedSegments)); } // packages ok? if (!package.DownloadStatus.ValidateRequestedParts(requestedSegments)) { logger.LogTrace($"Requested segments not valid for {package}: {requestedSegments.Format()}"); return(null, DataResponseFaul.CreateDataPackageSegmentsNotFoundMessage()); } // allocate slot int newUploadSlotsCount = Interlocked.Decrement(ref uploadSlots); if (newUploadSlotsCount <= 0) { // not enough slots Interlocked.Increment(ref uploadSlots); logger.LogTrace($"Peer choked when requested {package} segments: {requestedSegments.Format()}"); return(null, DataResponseFaul.CreateChokeMessage()); } // obtain lock if (!package.LockProvider.TryLock(out object lockToken)) { return(null, DataResponseFaul.CreateDataPackageNotFoundMessage()); } // create reader stream var sequencer = new PackagePartsSequencer(); logger.LogTrace($"Uploading for {package} segments: {requestedSegments.Format()}"); IEnumerable <PackageDataStreamPart> partsSource = sequencer.GetPartsForSpecificSegments(package.Reference.FolderPath, package.Sequence, requestedSegments); var controller = new ReadPackageDataStreamController(appInfo.LoggerFactory, package.Reference, package.Sequence, partsSource); var stream = new PackageDataStream(appInfo.LoggerFactory, controller) { Measure = package.UploadMeasure }; stream.Disposing += () => { int currentSlots = Interlocked.Increment(ref uploadSlots); package.LockProvider.Unlock(lockToken); }; return(stream, null); }
public IActionResult Data([FromBody] DataRequest request) { if (!packageRegistry.TryGetPackage(request.PackageHash, out LocalPackageInfo package) || package.LockProvider.IsMarkedToDelete) { return(new ObjectResult(DataResponseFaul.CreateDataPackageNotFoundMessage())); } // create stream var result = peersCluster.CreateUploadStream(package, request.RequestedParts); if (result.error != null) { return(new ObjectResult(result.error)); } return(new FileStreamResult(result.stream, "application/octet-stream")); }