public IList <RdcNeed> CreateNeedsList(SignatureInfo seedSignature, SignatureInfo sourceSignature, CancellationToken token) { var result = new List <RdcNeed>(); using (var seedStream = _seedSignatureRepository.GetContentForReading(seedSignature.Name)) using (var sourceStream = _sourceSignatureRepository.GetContentForReading(sourceSignature.Name)) { var fileReader = (IRdcFileReader) new RdcFileReader(seedStream); IRdcComparator comparator; if (_rdcLibrary.CreateComparator(fileReader, ComparatorBufferSize, out comparator) != 0) { throw new RdcException("Cannot create comparator"); } var inputBuffer = new RdcBufferPointer { Size = 0, Used = 0, Data = Marshal.AllocCoTaskMem(InputBufferSize + 16) }; var outputBuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(RdcNeed)) * 256); try { var eofInput = false; var eofOutput = false; var outputPointer = new RdcNeedPointer(); while (!eofOutput) { token.ThrowIfCancellationRequested(); if (inputBuffer.Size == inputBuffer.Used && !eofInput) { var bytesRead = 0; try { bytesRead = RdcBufferTools.IntPtrCopy(sourceStream, inputBuffer.Data, InputBufferSize); } catch (Exception ex) { throw new RdcException("Failed to read from the source stream.", ex); } inputBuffer.Size = (uint)bytesRead; inputBuffer.Used = 0; if (bytesRead < InputBufferSize) { eofInput = true; } } // Initialize our output needs array outputPointer.Size = 256; outputPointer.Used = 0; outputPointer.Data = outputBuffer; RdcError error; var hr = comparator.Process(eofInput, ref eofOutput, ref inputBuffer, ref outputPointer, out error); if (hr != 0) { throw new RdcException("Failed to process the signature block!", hr, error); } // Convert the stream to a Needs array. var needs = GetRdcNeedList(outputPointer); result.AddRange(needs); } } finally { // Free our resources if (outputBuffer != IntPtr.Zero) { Marshal.FreeCoTaskMem(outputBuffer); } if (inputBuffer.Data != IntPtr.Zero) { Marshal.FreeCoTaskMem(inputBuffer.Data); } } return(result); } }
/// <summary> /// Builds a comparator and perform the RDC comparison logic against the provided signatures to generate a needs list. /// </summary> /// <param name="seedSignature">Seed signature to compare</param> /// <param name="sourceSignature">Source signature to compare</param> /// <returns>RDC Needs list</returns> public ArrayList CreateNeedsList(SignatureInfo seedSignature, SignatureInfo sourceSignature) { int hr = 0; IRdcFileReader fileReader = (IRdcFileReader) new RdcFileReader(seedSignature.InnerStream); IRdcComparator comparator; GC.Collect(); GC.WaitForPendingFinalizers(); hr = rdcLibrary.CreateComparator(fileReader, 1000000, out comparator); // Create and allocate memory for our input buffer. IntPtr inputBuffer = Marshal.AllocCoTaskMem((int)inputBufferSize + 16); RdcBufferPointer inputPointer = new RdcBufferPointer(); inputPointer.size = 0; inputPointer.used = 0; inputPointer.data = inputBuffer; ArrayList needsList = new ArrayList(); IntPtr outputBuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(RdcNeed)) * 256); RdcNeedPointer outputPointer = new RdcNeedPointer(); long totalBytesRead = 0; bool eof = false; bool eofOutput = false; while (hr == 0 && !eofOutput) { if (inputPointer.size == inputPointer.used && !eof) { // Fill our input buffer with the signature // data from the source. // When the input buffer is completely empty // refill it. int bytesRead = 0; try { bytesRead = IntPtrCopy(sourceSignature.InnerStream, inputBuffer, 0, (int)inputBufferSize); } catch (Exception ex) { // TODO: Cleanup throw new RdcException("Failed to read from the source stream.", ex); } totalBytesRead += bytesRead; inputPointer.size = (uint)bytesRead; inputPointer.used = 0; if (bytesRead < inputBufferSize) { eof = true; } } // Initialize our output needs array outputPointer.size = 256; outputPointer.used = 0; outputPointer.data = outputBuffer; RdcError error = RdcError.NoError; // Perform the signature comparison. // This function may not produce needs output every time. // Also, it may not use all available input each time either. // You may call it with any number of input bytes // and output needs array entries. Obviously, it is more // efficient to give it reasonably sized buffers for each. // This sample waits until Process() consumes an entire input // buffer before reading more data from the source signatures file. // Continue calling this function until it sets "eofOutput" to true. hr = comparator.Process( eof, ref eofOutput, ref inputPointer, ref outputPointer, out error); if (hr != 0) { throw new RdcException("Failed to process the signature block!"); } if (error != RdcError.NoError) { throw new RdcException("Failed!"); } // Convert the stream to a Needs array. RdcNeed[] needs = GetRdcNeedList(outputPointer); foreach (RdcNeed need in needs) { // assign the needs to our arraylist. needsList.Add(need); } } if (hr != 0) { throw new RdcException("Failed!"); } // Free our resources if (outputBuffer != IntPtr.Zero) { Marshal.FreeCoTaskMem(outputBuffer); } if (inputBuffer != IntPtr.Zero) { Marshal.FreeCoTaskMem(inputBuffer); } return(needsList); }