In my attempts to understand the mechanics of TSIOBufferCopy I found the 
following function definition in InkIOCoreAPI.cc


int64_t

TSIOBufferCopy(TSIOBuffer bufp, TSIOBufferReader readerp, int64_t length, 
int64_t offset)

{

  sdk_assert(sdk_sanity_check_iocore_structure(bufp) == TS_SUCCESS);

  sdk_assert(sdk_sanity_check_iocore_structure(readerp) == TS_SUCCESS);

  sdk_assert((length >= 0) && (offset >= 0));


  MIOBuffer *b = (MIOBuffer *)bufp;

  IOBufferReader *r = (IOBufferReader *)readerp;


  return b->write(r, length, offset);

}


Note that it is undocumented but apparently the b->write(r, length, offset) 
does the work.


I believe I found the declaration of that function in I_IOBuffer.h  One thing 
that sort of stuck out to me in the set of code comments below, was the fact 
that it says


"Should it be necessary to make a large number of small transfers, it's 
preferable to use a interface that copies the data rather than sharing blocks 
to prevent

 a build of blocks on the buffer"


What confuses me is isn't TSIOBufferCopy supposed to be an interface that 
copies data rather than sharing blocks?



  /**

    Add by data from IOBufferReader r to the this buffer by reference. If

    len is INT64_MAX, all available data on the reader is added. If len is

    less than INT64_MAX, the smaller of len or the amount of data on the

    buffer is added. If offset is greater than zero, than the offset

    bytes of data at the front of the reader are skipped. Bytes skipped

    by offset reduce the number of bytes available on the reader used

    in the amount of data to add computation. write() does not respect

    watermarks or buffer size limits. Users of write must implement

    their own flow control. Returns the number of bytes added. Each

    write() call creates a new IOBufferBlock, even if it is for one

    byte. As such, it's necessary to exercise caution in any code that

    repeatedly transfers data from one buffer to another, especially if

    the data is being read over the network as it may be coming in very

    small chunks. Because deallocation of outstanding buffer blocks is

    recursive, it's possible to overrun the stack if too many blocks

    have been added to the buffer chain. It's imperative that users

    both implement their own flow control to prevent too many bytes

    from becoming outstanding on a buffer that the write() call is

    being used and that care be taken to ensure the transfers are of a

    minimum size. Should it be necessary to make a large number of small

    transfers, it's preferable to use a interface that copies the data

    rather than sharing blocks to prevent a build of blocks on the buffer.


  */

  inkcoreapi int64_t write(IOBufferReader * r, int64_t len = INT64_MAX, int64_t 
offset = 0);



 Also, the comments say that the return value of write is the actual number of 
bytes written.  Is it safe to assume that the return value will equal len 
should offset be 0?   If so, when you are simply trying to copy data from 
upstream to downstream and you subsequently make a calls such as:


/* Copy the data from the read buffer to the output buffer. */

bytesWritten = TSIOBufferCopy(TSVIOBufferGet(data->output_vio),

TSVIOReaderGet(input_vio), towrite, 0);


/* Tell the read buffer that we have read 'towrite' bytes of data

* and are no longer interested in it.

*/

TSIOBufferReaderConsume(TSVIOReaderGet(input_vio), bytesWritten);  // Should 
second param be bytesWritten or should it be towrite?


/* Increment the input VIO nDone value to reflect how much

* data we've copied from the upstream and written to the

* downstream.

*/

TSVIONDoneSet(input_vio, TSVIONDoneGet(input_vio) + bytesWritten); // Should 
Second param be TSVIONDoneGet(input_vio) + bytesWritten or 
TSVIONDoneGet(input_vio) + towrite?



Reply via email to