BlobSync.CommonOps.GenerateBlockDict C# (CSharp) Method

GenerateBlockDict() static private method

static private GenerateBlockDict ( BlockSignature sigArray ) : List>.Dictionary
sigArray BlobSync.Datatypes.BlockSignature
return List>.Dictionary
        internal static Dictionary<RollingSignature, List<BlockSignature>> GenerateBlockDict(BlockSignature[] sigArray)
        {
            var blockDict = new Dictionary<RollingSignature, List<BlockSignature>>();

            List<BlockSignature> bsl;
            foreach (var element in sigArray)
            {
                if (blockDict.TryGetValue(element.RollingSig, out bsl))
                {
                    var addToList = false;
                    // loop through sigs that have particular rolling sig and check for matching md5.
                    foreach (var bs in bsl)
                    {
                        // if md5's are different then throw exception, if they're the same can keep proceeding.
                        if (!bs.MD5Signature.SequenceEqual(element.MD5Signature))
                        {
                            // sig already exists... can happen, but hopefully rare.
                            addToList = true;
                        }
                        else
                        {
                            // matching md5....  so dont add to list.
                        }
                    }

                    if (addToList)
                    {
                        bsl.Add(element);
                    }
                }
                else
                {
                    bsl = new List<BlockSignature>();
                    bsl.Add(element);
                    blockDict[element.RollingSig] = bsl;
                }
            }

            return blockDict;
        }

Same methods

CommonOps::GenerateBlockDict ( CompleteSignature sig ) : List>.Dictionary

Usage Example

Example #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);
        }