Spot the defect (1/2): Custom Pipeline Component Sample "FixMsg" can fail without any apparent reason
Part 1 Part 2
Last week, I was trying to help Matthew with his custom pipeline component (see this newsgroup thread) .
To make a long story short, Matthew started from the custom pipeline component provided with BizTalk 2004 SDK (it gets installed into <BizTalk Install Dir>\SDK\Samples\Pipelines\CustomComponent) and specified a GUID to be put at the beginning of every file. Then, he composed this custom component (at decode stage) with a flat file disassembler. When executed, the following error showed up:
"SomePipeline.ReceivePipeline" Source: "Microsoft.BizTalk.Pipeline" Receive Location: "<some path>\*.000" Reason: Index was outside the bounds of the array.
We finally narrowed down the problem to be in the Read() routine of FixMsg, line 213, in (FixMsgStream.cs), The code reads as follow:
[ Some irrelevant code here ]
private byte[] prependData = null;
private byte[] appendData = null;
private int prependDataOffset = 0;
private int appendDataOffset = 0;
[ Some irrelevant code here ]
override public int Read(byte[] buffer, int offset, int count)
{
int ret = 0;
int bytesRead = 0;
if (prependData!=null)
{
bytesRead = count > prependData.Length ? prependData.Length : count;
Array.Copy(prependData, prependDataOffset, buffer, offset, bytesRead);
if (bytesRead==prependData.Length)
prependData = null; // prependData consumed
prependDataOffset += bytesRead;
offset += bytesRead;
count -= bytesRead;
ret += bytesRead;
}
bytesRead = stm.Read(buffer, offset, count); // <-- This is the offending line (213)
offset += bytesRead;
count -= bytesRead;
ret += bytesRead;
if ((bytesRead==0) && (appendData!=null))
{
// End of stream
bytesRead = count > appendData.Length ? appendData.Length : count;
Array.Copy(appendData, appendDataOffset, buffer, offset, bytesRead);
if (bytesRead==appendData.Length)
appendData = null; // appendData consumed
appendDataOffset += bytesRead;
ret += bytesRead;
}
return ret;
}
This Read() method above is supposed to implement the standard IStream.Read() function. prependData and appendData are two arrays of bytes, containing the data to prepend (put before the very first character of the message) and append (put after the very last character of the message). Observe that these two arrays can be empty (or null) which turns this custom pipeline component into a no-operation.
Matthew specified an hardcoded GUID for appendData so the length turned out to be 36 bytes (well, actually, he did put a comma “,” after so the size was actually 37 but this is irrelevant to the problem so let's ignore it for now).
Can you figure out what is wrong with that code without actually reading the newsgroup thread? Can you suggest ways for fixing this?
Hint: What happens if Read() is called twice, first with count = 10 and then count = 1024?
Comments
- Anonymous
July 06, 2004
Gilles,
I have read the tread so i know the answer... But what I don't get is the following,
The stream is handled in a complicated way....
Why not something like this.....(this is pseudo code)
stream a = BodyPart.GetOriginalDataStream
stream b = converttostream(prependdata)
stream c = converttostream(appenddata)
stream new = nothing
write new b
write new a
write new c
OutBodyPart.Data = new
The code would be much simpler....
I have the feeling i am missing something.
Why is the example so complicated..... - Anonymous
July 07, 2004
Patrick: Please refer to http://weblogs.asp.net/gzunino/archive/2004/07/07/175596.aspx