Hi. I made a plugin. it's almost same to null-transform plugin but has one more function.
it gets and delivers one of query string to transform so that it can sends on defined bit per second according to the value from each http transaction's query string. The difference between my plugin and null-transform is i made one more creation of continuation. In null-transform : TSPluginInit | |---------------> TSContCreate(transform_plugin) | |---------------->transform_plugin | |----------------> TSTransformCreate(null-transform) <---------- associate my data to transform itself. In my plugin TSPluginInit | |---------------> TSContCreate(transform_plugin) | |---------------->transform_plugin | |----------------> TSContCreate(txn_cont_handler) <------------------- one more creation of continuation and associate a value from query string to this continuation. | |--------------------------> txn_cont_handler | |-----------------------------> TSTransformCreate(null-transform) <--------- get the value from parent continuation and associate it to myself. Why did i create one more continuation? In the beginning i associated a value from query string to parent continuation in null-transform then made transform to get the value from the parent continuation. but i found other http requests overwrite the value in the parent continuation before the transform get the value from parent continuation!! so i hooked onto TS_EVENT_HTTP_TXN_START and made an grandpa continuation. so that the parent from grandpa continuation can keeps it's own value from the http transaction. at first it looks fine. it worked well. but when i repeated tests and checked memory leak. i found something wrong. the memory leak happens and finally traffic server down showing "insufficient memory". I did same test for null-transform and memory leak never happened. Of course i appended TSContDestroy as i created one more continuation. I repeated comparing null-transform and new-transform. i think i followed the steps after creation of continuation. I can't find what's wrong. This is cut out code(i'd like to remind you it's almost same to null-transform) : (if you wanna run my plugin i can send it. it's very simple code but you can see memory leak.) ... static void transform_add(TSHttpTxn txnp) { TSVConn connp; // create a transform here!! connp = TSTransformCreate(null_transform, txnp); TSHttpTxnHookAdd(txnp, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp); } static int txn_cont_handler(TSCont contp, TSEvent event, void *edata) { TSHttpTxn txnp = (TSHttpTxn) edata; switch (event) { case TS_EVENT_HTTP_READ_REQUEST_HDR : ... TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE : // ready to create transform transform_add(txnp); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; case TS_EVENT_HTTP_READ_RESPONSE_HDR : if (transformable(txnp)) { // ready to create transform transform_add(txnp); } TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; case TS_EVENT_HTTP_TXN_CLOSE : // Destroy continuation here!!! TSContDestroy(contp); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; default : break; } return 0; } static int h264_transform_plugin(TSCont contp, TSEvent event, void *edata) { TSHttpTxn txnp = (TSHttpTxn) edata; TSCont txn_contp; switch (event) { case TS_EVENT_HTTP_TXN_START : // Create parent continuation one more instead of creation of transform!! txn_contp = TSContCreate(txn_cont_handler, NULL); TSHttpTxnHookAdd(txnp, TS_HTTP_READ_REQUEST_HDR_HOOK, txn_contp); TSHttpTxnHookAdd(txnp, TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, txn_contp); TSHttpTxnHookAdd(txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, txn_contp); TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, txn_contp); TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE); return 0; default: break; } return 0; } void TSPluginInit(int argc, const char *argv[]) { TSPluginRegistrationInfo info; TSCont contp; // make a grandpa continuation contp = TSContCreate(h264_transform_plugin, NULL); // to save of query string TSHttpHookAdd(TS_HTTP_TXN_START_HOOK, contp); return; }