Example #1
0
        public static SignatureSearchResult SearchLocalFileForSignatures(string localFilePath, SizeBasedCompleteSignature sig)
        {
            var result = new SignatureSearchResult();

            // length of file.
            var tempFile   = File.Open(localFilePath, FileMode.Open);
            var fileLength = tempFile.Length;

            tempFile.Close();

            var offset       = 0;
            var windowSize   = ConfigHelper.SignatureSize;
            var windowBuffer = new byte[windowSize];

            // signatures we can reuse.
            var signaturesToReuse = new List <BlockSignature>();

            // get sizes of signatures (block sizes) from existing sig.
            // then loop through all sizes looking for matches in local file.
            // important to search from largest to smallest.
            var signatureSizes = sig.Signatures.Keys.ToList();

            signatureSizes.Sort();
            signatureSizes.Reverse();

            // byte ranges that have not been matched to existing blocks yet.
            var remainingByteList = new List <RemainingBytes>();

            remainingByteList.Add(new RemainingBytes {
                BeginOffset = 0, EndOffset = fileLength - 1
            });

            // Create the memory-mapped file.
            using (var mmf = MemoryMappedFile.CreateFromFile(localFilePath, FileMode.Open))
            {
                using (var accessor = mmf.CreateViewAccessor())
                {
                    // Any sigs smaller than 100 bytes? skip?
                    // Valid?
                    // Really want to avoid searching for single bytes everywhere.
                    foreach (var sigSize in signatureSizes)
                    {
                        var sigs = sig.Signatures[sigSize];
                        var newRemainingByteList = SearchLocalFileForSignaturesBasedOnSize(sigs, accessor, remainingByteList, sigSize, fileLength, signaturesToReuse);
                        remainingByteList = newRemainingByteList;
                    }
                }
            }

            result.ByteRangesToUpload = remainingByteList;
            result.SignaturesToReuse  = signaturesToReuse;
            return(result);
        }
Example #2
0
        // Uploads differences between existing blob and updated local file.
        // Have local file to reference, the search results (indicating which parts need to be uploaded)
        // container and blob name.
        private List <UploadedBlock> UploadDelta(string localFilePath, SignatureSearchResult searchResults, string containerName, string blobName, bool testMode = false)
        {
            var allUploadedBlocks = new List <UploadedBlock>();

            // loop through each section of the search results.
            // create blob from each RemainingBytes instances.
            // reuse the blocks already in use.
            foreach (var remainingBytes in searchResults.ByteRangesToUpload)
            {
                var uploadedBlockList = UploadBytesParallel(remainingBytes, localFilePath, containerName, blobName, testMode);
                //var uploadedBlockList = UploadBytes(remainingBytes, localFilePath, containerName, blobName, testMode);
                allUploadedBlocks.AddRange(uploadedBlockList);
            }

            // once we're here we should have uploaded ALL new data to Azure Blob Storage.
            // We then need to send the "construct" blob message.
            // loop through existing blocks and get offset + blockId's.
            foreach (var sig in searchResults.SignaturesToReuse)
            {
                if (sig.MD5Signature != null)
                {
                    var blockId = Convert.ToBase64String(sig.MD5Signature);
                    allUploadedBlocks.Add(new UploadedBlock()
                    {
                        BlockId = blockId, Offset = sig.Offset, Size = sig.Size, Sig = sig, IsNew = false
                    });
                }
            }

            if (!testMode)
            {
                // needs to be sorted by offset so the final blob constructed is in correct order.
                var res = (from b in allUploadedBlocks orderby b.Offset ascending select b.BlockId);
                PutBlockList(res.ToArray(), containerName, blobName);
            }

            return(allUploadedBlocks);
        }