sysctl_ctx_init.9 revision 63212

Copyright (c) 2000, Andrzej Bialecki <abial@freebsd.org>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

$FreeBSD: head/share/man/man9/sysctl_ctx_init.9 63212 2000-07-15 10:26:04Z abial $

.Dd Jul 15, 2000 .Dt sysctl_ctx_init 9 .Os FreeBSD 5.0 .Sh NAME .Nm sysctl_ctx_init , .Nm sysctl_ctx_free , .Nm sysctl_ctx_entry_add , .Nm sysctl_ctx_entry_find , .Nm sysctl_ctx_entry_del , .Nd sysctl context for managing dynamically created sysctl oids. .Sh SYNOPSIS .Fd #include <sys/sysctl.h> .Ft int .Fo sysctl_ctx_init .Fa "struct sysctl_ctx_list *clist" .Fc .Ft int .Fo sysctl_ctx_free .Fa "struct sysctl_ctx_list *clist" .Fc .Ft struct sysctl_ctx_entry * .Fo sysctl_ctx_entry_add .Fa "struct sysctl_ctx_list *clist" .Fa "struct sysctl_oid *oidp" .Fc .Ft struct sysctl_ctx_entry * .Fo sysctl_ctx_entry_find .Fa "struct sysctl_ctx_list *clist" .Fa "struct sysctl_oid *oidp" .Fc .Ft int .Fo sysctl_ctx_entry_del .Fa "struct sysctl_ctx_list *clist" .Fa "struct sysctl_oid *oidp" .Fc .Sh DESCRIPTION These functions allow to conveniently manage dynamically created oids. The sysctl context is responsible for keeping track of created oids, as well as their proper removal when needed. It adds simple transactional aspect to oid removal operation, i.e. if the removal operation fails in the middle, it's possible to rollback the sysctl tree to its previous state. .Fn sysctl_ctx_init initializes context. The .Va clist argument must point to already allocated variable. A context MUST be initialized before use. Once it's initialized, the pointer to the context can be passed as an argument to all SYSCTL_ADD_* macros, and it will be updated with entries pointing to newly created oids.

p Internally the context is represented as TAILQ linked list. The list consists of

a struct sysctl_ctx_entry entries: d -literal -offset indent struct sysctl_ctx_entry { struct sysctl_oid *entry; TAILQ_ENTRY(sysctl_ctx_entry) link; }; TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_entry); .Ed

p Each context entry points to one dynamic oid that it manages. Newly created oids are always inserted in the front of the list.

p .Fn sysctl_ctx_free removes the context and the oids it manages. If the function completes successfuly, all managed oids have been unregistered (removed from the tree) and freed, together with all their allocated memory, and the entries of the context have been freed as well. Removal operation is performed in two steps. First, for each context entry the function .Fn sysctl_remove_oid is executed, with parameter .Va del set to 0 (don't free resources, only unregister from the tree). If there are no errors during this step, .Fn sysctl_remove_oid proceeds to the next step. If the first step fails, all unregistered oids kept in the context are registered again. (NOTE: in most cases programmer specifies OID_AUTO as oid number when creating an oid. However, during registration of the oid in the tree, this number is changed to the first available number greater than 99. If the first step of context deletion fails, re-registration of the oid doesn't change the already assigned oid number (different from OID_AUTO), so that we are sure the re-registered entries are exactly on the same positions in the tree). The second step actually preforms deletion of dynamic oids. .Fn sysctl_remove_oid goes through the context list, starting from beginning (newest entries). IMPORTANT: this time the function not only deletes the oids from the tree, but also frees their memory (if oid_refcnt == 0), as well as all context entries.

p The .Fn sysctl_ctx_entry_add function allows to add existing dynamic oid to context.

p The .Fn sysctl_ctx_entry_del function removes entry from the context. IMPORTANT: in this case, only the corresponding

a sysctl_ctx_entry struct is freed, but

a sysctl_oid *oidp stays intact.

p The .Fn sysctl_ctx_entry_find function scans through the context list looking for given

a oidp , and either returns found

a sysctl_ctx_entry , or NULL.

p

p .Sh EXAMPLES The following code example shows how to create new top-level category and how to hook up another subtree to already existing (static) node, using contexts to keep track of the oids: d -literal #include <sys/sysctl.h> ... struct sysctl_ctx_list clist; struct sysctl_oid *oidp; int a_int; char *string = "dynamic sysctl"; ... sysctl_ctx_init(&clist); oidp = SYSCTL_ADD_NODE( &clist, SYSCTL_STATIC_CHILDREN(/* tree top */), OID_AUTO, newtree, CTFLAG_RW, 0, "new top level tree"); oidp = SYSCTL_ADD_INT( &clist, SYSCTL_CHILDREN(oidp), OID_AUTO, newint, CTLFLAG_RW, &a_int, 0, "new int leaf"); ... oidp = SYSCTL_ADD_NODE( &clist, SYSCTL_STATIC_CHILDREN(_debug), OID_AUTO, newtree, CTFLAG_RW, 0, "new tree under debug"); oidp = SYSCTL_ADD_STRING( &clist, SYSCTL_CHILDREN(oidp), OID_AUTO, newstring, CTLFLAG_R, string, 0, "new string leaf"); ... /* Now we can free up the oids */ if(sysctl_ctx_free(&clist)) { printf("can't free this context - other oids depend on it"); return(ENOTEMPTY); } else { printf("Success!\n"): return(0); } .Ed

p This example creates the following subtrees: d -literal -offset indent debug.newtree.newstring newtree.newint .Ed

p Then both trees are removed and their resources freed through one .Fn sysctl_ctx_free call, which starts with freeing the newest entried (leaves) and then proceeds to free the older entries (in this case the nodes).

p .Sh SEE ALSO .Xr sysctl_add_oid 9 , .Xr sysctl_remove_oid 9 , .Xr sysctl 8 , .Xr queue 3 .Sh HISTORY These functions appeared in .Fx 5.0 . .Sh AUTHORS .An Andrzej Bialecki Aq abial@FreeBSD.org .Sh BUGS Currently used removal algorithm is somewhat heavy (in the worst case all oids need to be unregistered, registered again, and then unregistered and deleted), but guarantees transactional properties for removal operation. All operations on the contexts involve traversing linked lists. For this reason creation and removal of entries is relatively costly.