Hi Steve, Did you get a chance already to have a look at http://trafficserver.apache.org/docs/v2/sdk/images/vconnection.jpg ? That image is from http://trafficserver.apache.org/docs/v2/sdk/HTTPTransformationPlugins.html#VIOs Both helped my understanding of the transformation api's
Regards, Otto 2013/1/25 Owens, Steve <[email protected]>: > One step closer > > VIO * > > PluginVC::do_io_write(Continuation * c, int64_t nbytes, IOBufferReader * > abuffer, bool owner) > > { > > > ink_assert(!closed); > > ink_assert(magic == PLUGIN_VC_MAGIC_ALIVE); > > > if (abuffer) { > > ink_assert(!owner); > > write_state.vio.buffer.reader_for(abuffer); > > } else { > > write_state.vio.buffer.clear(); > > } > > > // Note: we set vio.op last because process_write_side looks at it to > > // tell if the VConnection is active. > > write_state.vio.mutex = c->mutex; > > write_state.vio._cont = c; > > write_state.vio.nbytes = nbytes; > > write_state.vio.ndone = 0; > > write_state.vio.vc_server = (VConnection *) this; > > write_state.vio.op = VIO::WRITE; > > > Debug("pvc", "[%u] %s: do_io_write for %"PRId64" bytes", PVC_ID, PVC_TYPE, > nbytes); > > > // Since reentrant callbacks are not allowed on from do_io > > // functions schedule ourselves get on a different stack > > need_write_process = true; > > setup_event_cb(0, &sm_lock_retry_event); > > > return &write_state.vio; > > } > > > It would appear that the value passed in to the third argument of > TSVConnWrite ends up being assigned to write_state.vio.nbytes > > the docs on write_state.vio.nbytes state: > > /** > > Number of bytes to be done for this operation. > > > The total number of bytes this operation must complete. > > > */ > > int64_t nbytes; > > > So far clear as mud. Apologies in advance for my mental density. > > > > From: "Owens, Steve" <[email protected]> > Reply-To: "[email protected]" <[email protected]> > Date: Fri, 25 Jan 2013 11:09:08 -0800 > To: "[email protected]" <[email protected]> > Subject: Re: Api Questions > > An addendum to the previous message I have resorted to reading the traffic > server code in order to try to discern what it does: > > I am examining > > TSVIO > > TSVConnWrite(TSVConn connp, TSCont contp, TSIOBufferReader readerp, int64_t > nbytes) > > { > > sdk_assert(sdk_sanity_check_iocore_structure(connp) == TS_SUCCESS); > > sdk_assert(sdk_sanity_check_iocore_structure(contp) == TS_SUCCESS); > > sdk_assert(sdk_sanity_check_iocore_structure(readerp) == TS_SUCCESS); > > sdk_assert(nbytes >= 0); > > > FORCE_PLUGIN_MUTEX(contp); > > VConnection *vc = (VConnection *) connp; > > > return reinterpret_cast<TSVIO>(vc->do_io_write((INKContInternal *) contp, > nbytes, (IOBufferReader *) readerp)); > > } > > > It would appear that the answer to what this method does lies in what > happens in the function "vc->do_io_write" yet when I search the > trafficserver 3.2.0 codebase for any file that actually contains an > implementation of "vc->do_io_write" I find that "do_io_write" is declared in > several .h files but not defined in any .c or .cpp files. > > > Does anyone know where in the code base the implementation of "do_io_write" > resides? > > > > > From: "Owens, Steve" <[email protected]> > Reply-To: "[email protected]" <[email protected]> > Date: Fri, 25 Jan 2013 10:48:11 -0800 > To: "[email protected]" <[email protected]> > Subject: Api Questions > > I am trying to understand the relationship between the following functions > as they are used within a transformation plugin and so far no matter how > hard I dig the mystery remains. I am hoping that people who have a better > understanding of ATS than I do would be willing to help clear up any > misunderstandings I have. > > Here are the functions I find confusing: > > TSVIONBytesSet > > (TSIOBufferCopy and or TSIOBufferWrite) > > And finally > > TSVConnWrite > > > Each of the above functions takes an int_64 argument at the end to indicate > the number of bytes but I don't fully understand the purpose of this > parameter with respect to each of the functions. > > > Suppose I have a transformation which is intended to write a prefix spew the > response and then write a suffix to the down stream I would imagine it looks > something like this: > > > > > void handleTransformOperation(TSCont contp) { > > TSIOBuffer buf_test; > > int_64 written = 0; > > TransormationData* pData = (TransformationData*) TSContDataGet(contp); > > TSVIO input_vio = TSTransformOutputVConnGet(contp); > > > if(data->state == STATE_BEGIN) { > > // Initialize the output_buffer and output_reader > > data->output_buffer = TSIOBufferCreate(); > > data->output_reader = TSIOBufferReaderAlloc(data->output_buffer); > > > > // Write out a prefix > > written += TSIOBufferWrite(data->output_buffer, "{Hello I am a prefix}", > strlen(prefix) * sizeof(char)); > > data->state == STATE_MIDDLE; > > > // Figure out if the upstream wants to stop receiving WRITEREADY and > WRITE_COMPLETE events > > buf_test = TSVIOBufferGet(input_vio); > > if (!buf_test) { > > int64_t doneget = TSVIONDoneGet(input_vio); > > TSVIONBytesSet(data->output_vio, /*What goes here doneget or written > + doneget or just written? Bonus question: why? /* ???); > > data->state = STATE_END; > > } else > > data->state = STATE_MIDDLE; > > } > > > // Notice that the above if falls through to the next state so it is > possible that the following code may or may not > > // get executed based on the buf_test result above. > > if(data->state == STATE_MIDDLE) { > > // Figure out if the upstream wants to stop receiving WRITEREADY and > WRITE_COMPLETE events > > buf_test = TSVIOBufferGet(input_vio); > > if (!buf_test) { > > int64_t doneget = TSVIONDoneGet(input_vio); > > TSVIONBytesSet(data->output_vio, /*What goes here doneget or written > + doneget or just written? Bonus question: why? /* ???); > > data->state = STATE_END; > > } else { > > // Figure out how much data is left to read from the upstream > > int64_t upstreamBytesRemaining = TSVIONTodoGet(input_vio); > > int64_t upstreamBytesAvail = > TSIOBufferReaderAvail(TSVIOReaderGet(input_vio)); > > if(upstreamBytesRemaining > 0) { > > int64_t bytesToWrite = upstreamBytesRemaining; > > if(bytesToWrite > upstreamBytesAvail) > > bytesToWrite = upstreamBytesAvail; > > > > /* Copy the data from the read buffer to the output buffer. */ > > TSIOBufferCopy(TSVIOBufferGet(data->output_vio), > TSVIOReaderGet(input_vio), bytesToWrite, 0); > > > /* Tell the read buffer that we have read the data and are no > > * longer interested in it. > > */ > > TSIOBufferReaderConsume(TSVIOReaderGet(input_vio), bytesToWrite); > > > /* Modify the input VIO to reflect how much data we've > > * completed. > > */ > > int64_t doneget = TSVIONDoneGet(input_vio); > > TSVIONDoneSet(input_vio, /* This is where things get really muddy what > goes here? doneget or doneget + bytesToWrite or doneget + bytesToWrite + > written */ ??); > > /* What is the impact of calling this later in the handler if it > has already been called here? > > } > > > /* Now we check the input VIO to see if there is data left to > > * read. > > */ > > upstreamBytesRemaining = TSVIONTodoGet(input_vio); > > if (upstreamBytesRemaining > 0) { > > if (upstreamBytesAvail > 0) { > > /* If there is data left to read, then we reenable the output > > * connection by reenabling the output VIO. This will wake up > > * the output connection and allow it to consume data from the > > * output buffer. > > */ > > TSVIOReenable(data->output_vio); > > > /* Call back the input VIO continuation to let it know that we > > * are ready for more data. > > */ > > TSContCall(TSVIOContGet(input_vio), > > TS_EVENT_VCONN_WRITE_READY, input_vio); > > } > > } else { > > /* There is no data left to read so set state to STATE_END and */ > > data->state = STATE_END; > > } > > } > > > // The above can fall through to this if block > > if(data->state == STATE_END) { > > /* Spew a suffix */ > > const char* suffix = "{i am a suffix}"; > > int64_t localWritten = TSIOBufferWrite(data->output_buffer, suffix, > (strlen(suffix) - 1) * sizeof(char)); > > > > int64_t doneget = TSVIONDoneGet(input_vio); > > TSVIONBytesSet(data->output_vio, /* What goes here? Why? */??); > > TSVIOReenable(data->output_vio); > > > /* Call back the input VIO continuation to let it know that we > > * have completed the write operation. > > */ > > TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_COMPLETE, > input_vio); > > } > > > /* I am presuming we only want to call this once per invocation of > handlerOperation But I am not sure */ > > data->output_vio = TSVConnWrite(output_conn, contp, data->output_reader, > /* What to put here hmmm and why? */ ?? ); > > } > > > > I really want to understand how these methods relate and what they do. I > would be willing to help update/contribute to the ATS docs but first I would > need to understand what they do and so far the examples that are available > have not made it clear to me what is going on as yet so any help would be > appreciated. > > > >
