GenerateBlockDict() static private method

static private GenerateBlockDict ( BlockSignature sigArray ) : List>.Dictionary
sigArray BlobSync.Datatypes.BlockSignature
return List>.Dictionary
Exemplo n.º 1
0
        // regenerate blob locally.
        // we need to either download byte ranges from Azure.
        // OR
        // need to copy from local file.
        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);
        }