.\" Man page generated from reStructuredText. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "TSCONFIG FUNCTIONS" "3ts" "Jan 06, 2024" "9.2" "Apache Traffic Server" .SH NAME TSConfig Functions \- TSConfig API function .SH SYNOPSIS .INDENT 0.0 .INDENT 3.5 .sp .EX #include .EE .UNINDENT .UNINDENT .INDENT 0.0 .TP .B typedef void (*TSConfigDestroyFunc)(void*) .UNINDENT .INDENT 0.0 .TP .B unsigned int TSConfigSet(unsigned int id, void *data, \fI\%TSConfigDestroyFunc\fP funcp) .UNINDENT .INDENT 0.0 .TP .B \fI\%TSConfig\fP TSConfigGet(unsigned int id) .UNINDENT .INDENT 0.0 .TP .B void TSConfigRelease(unsigned int id, \fI\%TSConfig\fP configp) .UNINDENT .INDENT 0.0 .TP .B void *TSConfigDataGet(\fI\%TSConfig\fP configp) .UNINDENT .SH DESCRIPTION .sp These functions provide a mechanism to safely update configurations for a plugin. .sp If a plugin stores its configuration in a data structure, updating that structure due to changes in the configuration file can be dangerous due to the asynchronous nature of plugin callbacks. To avoid that problem these functions allow a plugin to register a configuration and then later replace it with another instance without changing the instance in use by plugin callbacks. This works in the same manner as \fI\%shared pointer\fP\&. When a plugin needs to access the configuration data, it calls \fI\%TSConfigGet()\fP which returns a pointer that will remain valid until the plugin calls \fI\%TSConfigRelease()\fP\&. The configuration instance is updated with \fI\%TSConfigSet()\fP which will update an internal pointer but will not change any instance in use via \fI\%TSConfigGet()\fP\&. When the last in use pointer is released, the old configuration is destructed using the function passed to func:\fITSConfigSet\fP\&. This handles the overlapping configuration update case correctly. .sp Initialization is done with \fI\%TSConfigSet()\fP\&. The \fIid\fP should be zero on the first call. This will allocate a slot for the configuration, which is returned. Subsequent calls must use this value. If the \fIid\fP is not zero, that value is returned. In general, the code will look something like .INDENT 0.0 .INDENT 3.5 .sp .EX class Config { ... }; // Configuration data. int Config_Id = 0; //... void ConfigUpdate() { Config* cfg = new Config; cfg.load(); // load config... Config_Id = TSConfigSet(Config_Id, cfg, [](void* cfg){delete static_cast(config);}); } //... PluginInit() { // ... ConfigUpdate(); // ... } .EE .UNINDENT .UNINDENT .sp \fBConfig_Id\fP is a global variable holding the configuration id, which is updated by the return value of \fI\%TSConfigSet()\fP\&. .sp The configuration instance is retrieved with \fI\%TSConfigGet()\fP\&. This returns a wrapper class from which the configuration can be extracted with \fI\%TSConfigDataGet()\fP\&. The wrapper is used to release the configuration instance when it is no longer in use. The code in a callback tends to look like .INDENT 0.0 .INDENT 3.5 .sp .EX int callback() { auto cfg_ref = TSConfigGet(Config_Id); Config* cfg = static_cast(TSConfigDataGet(cfg_ref)); // ... use cfg TSConfigRelease(Config_Id, cfg_ref); } .EE .UNINDENT .UNINDENT .SH COPYRIGHT 2024, dev@trafficserver.apache.org .\" Generated by docutils manpage writer. .