BlobSync.AzureOps.RegenerateBlob C# (CSharp) Method

RegenerateBlob() private method

private RegenerateBlob ( string containerName, string blobName, List byteRangesToDownload, string localFilePath, List reusableBlockSignatures, SizeBasedCompleteSignature blobSig, int parallelFactor = 2 ) : void
containerName string
blobName string
byteRangesToDownload List
localFilePath string
reusableBlockSignatures List
blobSig BlobSync.Datatypes.SizeBasedCompleteSignature
parallelFactor int
return void
        private void RegenerateBlob(string containerName, string blobName, List<RemainingBytes> byteRangesToDownload, string localFilePath, List<BlockSignature> reusableBlockSignatures, SizeBasedCompleteSignature blobSig, int parallelFactor = 2)
        {
            // removing size from the equation.
            var allBlobSigs =
                blobSig.Signatures.Values.SelectMany(x => x.SignatureList).OrderBy(a => a.Offset).ToList();

            // LUT to see if block is to be reused or not.
            var reusableBlockDict = CommonOps.GenerateBlockDict(reusableBlockSignatures.ToArray());

            var offset = 0L;

            using (var localStream = new FileStream( localFilePath, FileMode.Open))
            using (var newStream = new FileStream( localFilePath+".new", FileMode.Create))
            {
                // go through all sigs in offset order....  determine if can reuse or need to download.
                foreach (var sig in allBlobSigs)
                {
                    var haveMatch = false;
                    if (reusableBlockDict.ContainsKey(sig.RollingSig))
                    {
                        // have a match... so will reuse local file.
                        var localSig = reusableBlockDict[sig.RollingSig];

                        var matchingLocalSigs =
                                localSig.Where(s => s.MD5Signature.SequenceEqual(sig.MD5Signature))
                                    .Select(n => n)
                                    .ToList();

                        if (matchingLocalSigs.Any())
                        {
                            // have a match.
                            var matchingLocalSig = matchingLocalSigs[0];

                            // huge amount of wasted allocations...  maybe move this.
                            var buffer = new byte[matchingLocalSig.Size];

                            localStream.Seek(matchingLocalSig.Offset, SeekOrigin.Begin);
                            localStream.Read(buffer, 0, (int) matchingLocalSig.Size);

                            newStream.Seek(sig.Offset, SeekOrigin.Begin);
                            newStream.Write( buffer, 0, (int) matchingLocalSig.Size);

                            haveMatch = true;
                            offset += matchingLocalSig.Size;
                        }

                    }

                    if (!haveMatch)
                    {
                        // check if we have byte ranges starting at offset.
                        var byteRange =
                            (from b in byteRangesToDownload where b.BeginOffset == offset select b).FirstOrDefault();
                        if (byteRange != null)
                        {
                            // download bytes.
                            var blobBytes = DownloadBytes(containerName, blobName, byteRange.BeginOffset,
                                byteRange.EndOffset, parallelFactor);

                            newStream.Seek(sig.Offset, SeekOrigin.Begin);
                            newStream.Write(blobBytes, 0, (int)(byteRange.EndOffset - byteRange.BeginOffset + 1));

                            offset += (byteRange.EndOffset - byteRange.BeginOffset + 1);
                        }
                    }
                }
            }

            // rename .new file to original
            File.Replace(localFilePath + ".new", localFilePath,null);
        }