4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
36 #include <sys/loadavg.h>
37 #include <sys/types.h>
38 #include <sys/utsname.h>
41 #include "pool_internal.h"
42 #include "pool_impl.h"
45 * Atom structure, used to reference count string atoms.
48 char *a_string
; /* String atom */
49 uint_t a_count
; /* String reference count */
53 * The _internal_lock is used to lock the state of libpool during
54 * internal initialisation operations.
56 mutex_t _internal_lock
;
58 static int _libpool_debug
= 0; /* debugging messages */
59 static dict_hdl_t
*_pv_atoms
; /* pool_value_t atoms */
60 static mutex_t _atom_lock
; /* atom table lock */
61 static int _libpool_internal_initialised
= PO_FALSE
;
64 * Various useful constant strings which are often encountered
66 const char *c_a_dtype
= "a-dtype";
67 const char *c_name
= "name";
68 const char *c_type
= "type";
69 const char *c_ref_id
= "ref_id";
70 const char *c_max_prop
= "max";
71 const char *c_min_prop
= "min";
72 const char *c_size_prop
= "size";
73 const char *c_sys_prop
= "sys_id";
76 * prop_is_type() checks the supplied property and returns PO_TRUE if the
77 * property value is set for the property else PO_FALSE
79 static int prop_is_type(int, const pool_prop_t
*);
80 static int resource_get_common(const pool_resource_t
*, const char *,
82 static int64_t elem_get_expected_int64(const pool_elem_t
*, const char *);
85 * The following returns a malloc'ed string which must be free'd by the
88 static char *elem_get_expected_string(const pool_elem_t
*, const char *);
89 static int element_props_init(pool_prop_t
*);
92 * Each element class/sub-class has a set of properties and behaviours
93 * which are used to create the element with appropriate property
94 * values and to ensure correct property manipulations. The details
95 * are all stored in the following arrays.
98 static int elem_name_init(pool_prop_t
*);
99 static int elem_comment_init(pool_prop_t
*);
101 static int pool_importance_init(pool_prop_t
*);
102 static int pool_active_init(pool_prop_t
*);
104 static int res_max_init(pool_prop_t
*);
105 static int res_min_init(pool_prop_t
*);
106 static int res_size_init(pool_prop_t
*);
107 static int res_load_init(pool_prop_t
*);
109 static int pset_units_init(pool_prop_t
*);
111 static int cpu_status_init(pool_prop_t
*);
113 static int elem_no_set(pool_elem_t
*, const pool_value_t
*);
114 static int elem_set_name(pool_elem_t
*, const pool_value_t
*);
115 static int elem_get_type(const pool_elem_t
*, pool_value_t
*);
116 static int elem_set_string(pool_elem_t
*, const pool_value_t
*);
117 static int elem_set_bool(pool_elem_t
*, const pool_value_t
*);
118 static int elem_set_uint(pool_elem_t
*, const pool_value_t
*);
120 static int system_set_allocate(pool_elem_t
*, const pool_value_t
*);
122 static int pool_set_scheduler(pool_elem_t
*, const pool_value_t
*);
123 static int pool_set_active(pool_elem_t
*, const pool_value_t
*);
125 static int res_set_max(pool_elem_t
*, const pool_value_t
*);
126 static int res_set_min(pool_elem_t
*, const pool_value_t
*);
128 static int cpu_set_status(pool_elem_t
*, const pool_value_t
*);
130 static const char *pool_elem_class_name
[] = {
134 "component resource",
135 "aggregate resource",
140 * This must be kept in sync with the pool_resource_elem_ctl array and
141 * the "enum pool_resource_elem_class" type.
143 static const char *pool_resource_elem_class_name
[] = {
148 static const char *pool_component_elem_class_name
[] = {
153 static pool_prop_t system_props
[] = {
154 { "system.name", POOL_VALUE_INITIALIZER
, PP_STORED
, NULL
,
155 { NULL
, elem_set_name
} },
156 { "system.ref_id", POOL_VALUE_INITIALIZER
,
157 PP_HIDDEN
| PP_STORED
| PP_READ
, NULL
, { NULL
, elem_no_set
} },
158 { "system.comment", POOL_VALUE_INITIALIZER
, PP_STORED
, NULL
, NULL
},
159 { "system.version", POOL_VALUE_INITIALIZER
,
160 PP_STORED
| PP_READ
, NULL
, NULL
},
161 { "system.bind-default", POOL_VALUE_INITIALIZER
,
162 PP_STORED
, NULL
, NULL
},
163 { "system.allocate-method", POOL_VALUE_INITIALIZER
,
164 PP_STORED
| PP_OPTIONAL
, NULL
, { NULL
, system_set_allocate
} },
165 { "system.poold.log-level", POOL_VALUE_INITIALIZER
,
166 PP_STORED
| PP_OPTIONAL
, NULL
, { NULL
, elem_set_string
} },
167 { "system.poold.log-location", POOL_VALUE_INITIALIZER
,
168 PP_STORED
| PP_OPTIONAL
, NULL
, { NULL
, elem_set_string
} },
169 { "system.poold.monitor-interval", POOL_VALUE_INITIALIZER
,
170 PP_STORED
| PP_OPTIONAL
, NULL
, { NULL
, elem_set_uint
} },
171 { "system.poold.history-file", POOL_VALUE_INITIALIZER
,
172 PP_STORED
| PP_OPTIONAL
, NULL
, { NULL
, elem_set_string
} },
173 { "system.poold.objectives", POOL_VALUE_INITIALIZER
,
174 PP_STORED
| PP_OPTIONAL
, NULL
, { NULL
, elem_set_string
} },
178 static pool_prop_t pool_props
[] = {
179 { "pool.sys_id", POOL_VALUE_INITIALIZER
,
180 PP_STORED
| PP_READ
, NULL
, NULL
},
181 { "pool.name", POOL_VALUE_INITIALIZER
,
182 PP_STORED
| PP_INIT
, elem_name_init
, { NULL
, elem_set_name
} },
183 { "pool.res", POOL_VALUE_INITIALIZER
,
184 PP_HIDDEN
| PP_STORED
| PP_READ
, NULL
, { NULL
, elem_no_set
} },
185 { "pool.ref_id", POOL_VALUE_INITIALIZER
,
186 PP_HIDDEN
| PP_STORED
| PP_READ
, NULL
, { NULL
, elem_no_set
} },
187 { "pool.active", POOL_VALUE_INITIALIZER
, PP_STORED
| PP_INIT
,
188 pool_active_init
, { NULL
, pool_set_active
} },
189 { "pool.default", POOL_VALUE_INITIALIZER
,
190 PP_STORED
| PP_READ
, NULL
, NULL
},
191 { "pool.scheduler", POOL_VALUE_INITIALIZER
,
192 PP_STORED
| PP_OPTIONAL
, NULL
,
193 { NULL
, pool_set_scheduler
} },
194 { "pool.importance", POOL_VALUE_INITIALIZER
, PP_STORED
| PP_INIT
,
195 pool_importance_init
, NULL
},
196 { "pool.comment", POOL_VALUE_INITIALIZER
, PP_STORED
| PP_INIT
,
197 elem_comment_init
, NULL
},
201 static pool_prop_t pset_props
[] = {
202 { "type", POOL_VALUE_INITIALIZER
, PP_HIDDEN
| PP_STORED
| PP_READ
, NULL
,
203 { elem_get_type
, NULL
} },
204 { "pset.sys_id", POOL_VALUE_INITIALIZER
,
205 PP_STORED
| PP_READ
, NULL
, NULL
},
206 { "pset.name", POOL_VALUE_INITIALIZER
,
207 PP_STORED
| PP_INIT
, elem_name_init
, { NULL
, elem_set_name
} },
208 { "pset.ref_id", POOL_VALUE_INITIALIZER
,
209 PP_HIDDEN
| PP_STORED
| PP_READ
, NULL
, { NULL
, elem_no_set
} },
210 { "pset.default", POOL_VALUE_INITIALIZER
,
211 PP_STORED
| PP_READ
, NULL
, NULL
},
212 { "pset.min", POOL_VALUE_INITIALIZER
, PP_STORED
| PP_INIT
, res_min_init
,
213 { NULL
, res_set_min
} },
214 { "pset.max", POOL_VALUE_INITIALIZER
, PP_STORED
| PP_INIT
, res_max_init
,
215 { NULL
, res_set_max
} },
216 { "pset.units", POOL_VALUE_INITIALIZER
,
217 PP_STORED
| PP_INIT
, pset_units_init
, NULL
},
218 { "pset.load", POOL_VALUE_INITIALIZER
, PP_READ
| PP_INIT
,
219 res_load_init
, NULL
},
220 { "pset.size", POOL_VALUE_INITIALIZER
, PP_STORED
| PP_INIT
| PP_READ
,
221 res_size_init
, NULL
},
222 { "pset.comment", POOL_VALUE_INITIALIZER
, PP_STORED
| PP_INIT
,
223 elem_comment_init
, NULL
},
224 { "pset.poold.objectives", POOL_VALUE_INITIALIZER
,
225 PP_STORED
| PP_OPTIONAL
, NULL
, { NULL
, elem_set_string
} },
229 static pool_prop_t cpu_props
[] = {
230 { "type", POOL_VALUE_INITIALIZER
, PP_HIDDEN
| PP_STORED
| PP_READ
, NULL
,
231 { elem_get_type
, NULL
} },
232 { "cpu.sys_id", POOL_VALUE_INITIALIZER
, PP_STORED
| PP_READ
, NULL
,
234 { "cpu.ref_id", POOL_VALUE_INITIALIZER
,
235 PP_HIDDEN
| PP_STORED
| PP_READ
, NULL
, { NULL
, elem_no_set
} },
236 { "cpu.comment", POOL_VALUE_INITIALIZER
, PP_STORED
| PP_INIT
,
237 elem_comment_init
, NULL
},
238 { "cpu.status", POOL_VALUE_INITIALIZER
, PP_INIT
, cpu_status_init
,
239 { NULL
, cpu_set_status
} },
240 { "cpu.pinned", POOL_VALUE_INITIALIZER
, PP_STORED
| PP_OPTIONAL
, NULL
,
241 { NULL
, elem_set_bool
} },
245 static pool_prop_t
*pool_elem_ctl
[] = {
255 * This must be kept in sync with the pool_resource_elem_class_name array and
256 * the "enum pool_resource_elem_class" type.
258 static pool_prop_t
*pool_resource_elem_ctl
[] = {
263 static pool_prop_t
*pool_component_elem_ctl
[] = {
271 (void) mutex_lock(&_atom_lock
);
273 * Initialize pool_value_t atom dictionary
275 if (_pv_atoms
== NULL
)
276 if ((_pv_atoms
= dict_new((int (*)(const void *, const void *))
277 strcmp
, (uint64_t (*)(const void *))hash_str
)) == NULL
)
279 (void) mutex_unlock(&_atom_lock
);
283 * Initializer, called when the library is initialized.
288 (void) mutex_lock(&_internal_lock
);
289 if (_libpool_internal_initialised
== PO_TRUE
) {
290 (void) mutex_unlock(&_internal_lock
);
295 * Initialize all available property arrays.
297 if (element_props_init(system_props
) == PO_FAIL
)
299 if (element_props_init(pool_props
) == PO_FAIL
)
301 if (element_props_init(pset_props
) == PO_FAIL
)
303 if (element_props_init(cpu_props
) == PO_FAIL
)
305 _libpool_internal_initialised
= PO_TRUE
;
306 (void) mutex_unlock(&_internal_lock
);
311 element_props_init(pool_prop_t
*props
)
315 for (i
= 0; props
[i
].pp_pname
!= NULL
; i
++) {
317 * Initialise each of the properties
319 if (pool_value_set_name(&props
[i
].pp_value
,
320 props
[i
].pp_pname
) != PO_SUCCESS
) {
323 if (props
[i
].pp_init
&&
324 props
[i
].pp_init(&props
[i
]) != PO_SUCCESS
) {
333 * These functions intialise the properties of this plugin. The only reason
334 * they exist is because the ability to perform the static initialisation of
335 * union members properly was only introduced in the C99 standard. i.e. if you
336 * could do {.f = 1.0} like in the proposed C99 standard then that would
337 * be the preferred way to do this as it keeps the data in the array and
338 * minimises the scope for errors. However, until that time these functions
339 * are the best way to minimise the scope for errors and to maximise
342 * There is one function for each property, and the initial value for each
343 * property is hard-coded into each function.
347 elem_name_init(pool_prop_t
*prop
)
349 return (string_init(prop
, "default"));
353 elem_comment_init(pool_prop_t
*prop
)
355 return (string_init(prop
, ""));
359 pool_importance_init(pool_prop_t
*prop
)
361 return (int_init(prop
, 1));
365 pool_active_init(pool_prop_t
*prop
)
367 return (bool_init(prop
, PO_TRUE
));
371 res_max_init(pool_prop_t
*prop
)
373 return (uint_init(prop
, 0));
377 res_min_init(pool_prop_t
*prop
)
379 return (uint_init(prop
, 0));
383 res_size_init(pool_prop_t
*prop
)
385 return (uint_init(prop
, 0));
389 res_load_init(pool_prop_t
*prop
)
391 return (uint_init(prop
, 0));
395 pset_units_init(pool_prop_t
*prop
)
397 return (string_init(prop
, "population"));
401 cpu_status_init(pool_prop_t
*prop
)
403 return (string_init(prop
, PS_ONLINE
));
407 * Individual property manipulation routines for use by the generic
408 * get/put property routines
412 * Many properties cannot be modified. This function prevents property
417 elem_no_set(pool_elem_t
*elem
, const pool_value_t
*pval
)
423 * Duplicate names for a pool or resource type are illegal.
426 elem_set_name(pool_elem_t
*elem
, const pool_value_t
*pval
)
430 pool_resource_t
*res
;
432 if (pool_value_get_string(pval
, &nm
) != PO_SUCCESS
) {
435 if (!is_valid_name(nm
)) {
436 pool_seterror(POE_PUTPROP
);
439 switch (pool_elem_class(elem
)) {
443 pool
= pool_get_pool(TO_CONF(elem
), nm
);
444 if (pool
!= NULL
&& pool
!= pool_elem_pool(elem
)) {
445 pool_seterror(POE_PUTPROP
);
451 res
= pool_get_resource(TO_CONF(elem
),
452 pool_elem_class_string(elem
), nm
);
453 if (res
!= NULL
&& res
!= pool_elem_res(elem
)) {
454 pool_seterror(POE_PUTPROP
);
465 * Ensure the type is a string.
469 elem_set_string(pool_elem_t
*elem
, const pool_value_t
*pval
)
471 if (pool_value_get_type(pval
) == POC_STRING
)
474 pool_seterror(POE_BADPARAM
);
480 * Ensure the type is a boolean.
484 elem_set_bool(pool_elem_t
*elem
, const pool_value_t
*pval
)
486 if (pool_value_get_type(pval
) == POC_BOOL
)
489 pool_seterror(POE_BADPARAM
);
495 * Ensure the type is an unsigned int.
499 elem_set_uint(pool_elem_t
*elem
, const pool_value_t
*pval
)
501 if (pool_value_get_type(pval
) == POC_UINT
)
504 pool_seterror(POE_BADPARAM
);
511 system_set_allocate(pool_elem_t
*elem
, const pool_value_t
*pval
)
515 if (pool_value_get_string(pval
, &sval
) != PO_SUCCESS
) {
516 pool_seterror(POE_PUTPROP
);
519 if (strcmp(POA_IMPORTANCE
, sval
) != 0 &&
520 strcmp(POA_SURPLUS_TO_DEFAULT
, sval
) != 0) {
521 pool_seterror(POE_PUTPROP
);
529 pool_set_active(pool_elem_t
*elem
, const pool_value_t
*pval
)
533 if (pool_value_get_type(pval
) != POC_BOOL
) {
534 pool_seterror(POE_BADPARAM
);
537 (void) pool_value_get_bool(pval
, &bval
);
540 * "active" must be true on pools for
543 pool_seterror(POE_BADPARAM
);
551 pool_set_scheduler(pool_elem_t
*elem
, const pool_value_t
*pval
)
556 if (pool_value_get_string(pval
, &sched
) != 0) {
557 pool_seterror(POE_PUTPROP
);
560 (void) strncpy(pcinfo
.pc_clname
, sched
, PC_CLNMSZ
);
561 if (priocntl(0, 0, PC_GETCID
, &pcinfo
) == -1) {
562 pool_seterror(POE_PUTPROP
);
569 res_set_max(pool_elem_t
*elem
, const pool_value_t
*pval
)
572 pool_value_t val
= POOL_VALUE_INITIALIZER
;
577 if (pool_value_get_uint64(pval
, &max
) != PO_SUCCESS
) {
578 pool_seterror(POE_PUTPROP
);
582 * max can't be less than min (if it exists)
584 if (pool_get_ns_property(elem
, c_min_prop
, &val
) == POC_INVAL
)
586 if (pool_value_get_uint64(&val
, &min
) != PO_SUCCESS
) {
587 pool_seterror(POE_PUTPROP
);
591 pool_seterror(POE_PUTPROP
);
595 * Ensure that changes to the max in a dynamic configuration
598 if (conf_is_dynamic(TO_CONF(elem
)) == PO_TRUE
) {
601 if (pool_get_ns_property(elem
, c_max_prop
, &val
) == POC_INVAL
) {
602 pool_seterror(POE_PUTPROP
);
605 if (pool_value_get_uint64(&val
, &oldmax
) != PO_SUCCESS
) {
606 pool_seterror(POE_PUTPROP
);
611 * Ensure that the modified total max is >= size
612 * of all resources of this type
614 return (pool_validate_resource(TO_CONF(elem
),
615 pool_elem_class_string(elem
), c_max_prop
,
623 res_set_min(pool_elem_t
*elem
, const pool_value_t
*pval
)
626 pool_value_t val
= POOL_VALUE_INITIALIZER
;
631 if (pool_value_get_uint64(pval
, &min
) != PO_SUCCESS
) {
632 pool_seterror(POE_PUTPROP
);
636 * min can't be more than max (if it exists)
638 if (pool_get_ns_property(elem
, c_max_prop
, &val
) == POC_INVAL
)
640 if (pool_value_get_uint64(&val
, &max
) != PO_SUCCESS
) {
641 pool_seterror(POE_PUTPROP
);
645 pool_seterror(POE_PUTPROP
);
649 switch (pool_resource_elem_class(elem
)) {
651 if (resource_is_default(pool_elem_res(elem
))) {
653 pool_seterror(POE_PUTPROP
);
663 * Ensure that changes to the min in a dynamic configuration
666 if (conf_is_dynamic(TO_CONF(elem
)) == PO_TRUE
) {
669 if (pool_get_ns_property(elem
, c_min_prop
, &val
) == POC_INVAL
) {
670 pool_seterror(POE_PUTPROP
);
673 if (pool_value_get_uint64(&val
, &oldmin
) != PO_SUCCESS
) {
674 pool_seterror(POE_PUTPROP
);
679 * Ensure that the modified total min is <= size
680 * of all resources of this type
682 return (pool_validate_resource(TO_CONF(elem
),
683 pool_elem_class_string(elem
), c_min_prop
,
692 cpu_set_status(pool_elem_t
*elem
, const pool_value_t
*pval
)
696 if (pool_value_get_string(pval
, &status
) != 0) {
697 pool_seterror(POE_PUTPROP
);
701 if (strcmp(PS_ONLINE
, status
) != 0 &&
702 strcmp(PS_OFFLINE
, status
) != 0 &&
703 strcmp(PS_NOINTR
, status
) != 0 &&
704 strcmp(PS_SPARE
, status
) != 0 &&
705 strcmp(PS_FAULTED
, status
) != 0) {
706 pool_seterror(POE_PUTPROP
);
713 elem_get_type(const pool_elem_t
*elem
, pool_value_t
*pval
)
715 if (pool_value_set_string(pval
, pool_elem_class_string(elem
)) ==
722 * More general utilities
725 * Is the supplied configuration the dynamic configuration
726 * Return: PO_TRUE/PO_FALSE
729 conf_is_dynamic(const pool_conf_t
*conf
)
731 if (strcmp(pool_conf_location(conf
), pool_dynamic_location()) == 0)
737 * uint_init() initialises the value of the supplied property with the
742 uint_init(pool_prop_t
*prop
, uint64_t val
)
744 pool_value_set_uint64(&prop
->pp_value
, val
);
749 * int_init() initialises the value of the supplied property with the
754 int_init(pool_prop_t
*prop
, int64_t val
)
756 pool_value_set_int64(&prop
->pp_value
, val
);
761 * double_init() initialises the value of the supplied property with the
766 double_init(pool_prop_t
*prop
, double val
)
768 pool_value_set_double(&prop
->pp_value
, val
);
773 * bool_init() initialises the value of the supplied property with the
778 bool_init(pool_prop_t
*prop
, uchar_t val
)
780 pool_value_set_bool(&prop
->pp_value
, val
);
785 * string_init() initialises the value of the supplied property with the
787 * Returns PO_SUCCESS/PO_FAIL
790 string_init(pool_prop_t
*prop
, const char *val
)
792 return (pool_value_set_string(&prop
->pp_value
, val
));
796 * pool_get_provider_count() returns the count of registered providers.
798 * Returns count of registered providers
801 pool_get_provider_count(void)
806 for (i
= 0; i
< sizeof (pool_resource_elem_ctl
) /
807 sizeof (pool_resource_elem_ctl
[0]); i
++) {
808 if (pool_resource_elem_ctl
[i
] != NULL
)
815 * Return all the props for a specified provider
818 provider_get_props(const pool_elem_t
*elem
)
820 const pool_prop_t
*prop_list
= NULL
;
821 pool_elem_class_t elem_class
= pool_elem_class(elem
);
823 switch (elem_class
) {
826 prop_list
= pool_elem_ctl
[elem_class
];
830 prop_list
= pool_resource_elem_ctl
831 [pool_resource_elem_class(elem
)];
834 prop_list
= pool_component_elem_ctl
835 [pool_component_elem_class(elem
)];
842 * provider_get_prop() return the pool_prop_t structure which
843 * describes the supplied property name for the supplied provider.
845 * Returns the property description or NULL if it doesn't exist.
848 provider_get_prop(const pool_elem_t
*elem
, const char *name
)
851 const pool_prop_t
*prop_list
;
853 if ((prop_list
= provider_get_props(elem
)) == NULL
)
856 for (i
= 0; prop_list
[i
].pp_pname
!= NULL
; i
++) {
857 if (strcmp(name
, prop_list
[i
].pp_pname
) == 0) {
858 return (&prop_list
[i
]);
865 * prop_is_type() checks the supplied property and returns PO_TRUE if the
866 * property value is 1 else PO_FALSE
869 prop_is_type(int prop_type
, const pool_prop_t
*prop
)
871 return ((prop
->pp_perms
& prop_type
) ? PO_TRUE
: PO_FALSE
);
875 * prop_is_stored() returns PO_TRUE if the property is stored in the backing
876 * configuration and PO_FALSE else.
879 prop_is_stored(const pool_prop_t
*prop
)
881 return (prop_is_type(PP_STORED
, prop
));
885 * prop_is_readonly() returns PO_TRUE if the property is a read-only property
889 prop_is_readonly(const pool_prop_t
*prop
)
891 return (prop_is_type(PP_READ
, prop
));
895 * prop_is_init() returns PO_TRUE if the property should be
896 * initialised when an element of this type is created and PO_FALSE
900 prop_is_init(const pool_prop_t
*prop
)
902 return (prop_is_type(PP_INIT
, prop
));
906 * prop_is_hidden() returns PO_TRUE if the property should be hidden
907 * from access by the external property access mechanisms.
910 prop_is_hidden(const pool_prop_t
*prop
)
912 return (prop_is_type(PP_HIDDEN
, prop
));
916 * prop_is_optional() returns PO_TRUE if the property is optional and
917 * can be removed by external property access mechanisms.
920 prop_is_optional(const pool_prop_t
*prop
)
922 return (prop_is_type(PP_OPTIONAL
, prop
));
926 cpu_is_requested(pool_component_t
*component
)
928 pool_value_t val
= POOL_VALUE_INITIALIZER
;
931 if (pool_get_property(TO_CONF(TO_ELEM(component
)), TO_ELEM(component
),
932 "cpu.requested", &val
) != POC_BOOL
) {
935 if (pool_value_get_bool(&val
, &requested
) != PO_SUCCESS
) {
938 return ((int)requested
);
942 * Common code for various resource get functions
945 resource_get_common(const pool_resource_t
*res
, const char *name
,
948 pool_value_t val
= POOL_VALUE_INITIALIZER
;
949 pool_value_class_t pvc
;
950 int retval
= PO_SUCCESS
;
952 pvc
= pool_get_ns_property(TO_ELEM(res
), name
, &val
);
953 if (pvc
== POC_INVAL
) {
956 dprintf("can't retrieve %s\n");
957 pool_elem_dprintf(TO_ELEM(res
));
959 } else if (pvc
== POC_UINT
) {
960 retval
= pool_value_get_uint64(&val
, uval
);
966 * resource_get_size() updates size with the size of the supplied resource.
968 * Returns PO_SUCCESS/PO_FAIL
971 resource_get_size(const pool_resource_t
*res
, uint64_t *size
)
973 return (resource_get_common(res
, c_size_prop
, size
));
977 * resource_get_pinned() updates pinned with the size of the
978 * pinned part of a supplied resource. Resource is not available for
979 * allocation if it is marked as "pinned".
981 * Returns PO_SUCCESS/PO_FAIL
984 resource_get_pinned(const pool_resource_t
*res
, uint64_t *pinned
)
986 pool_value_t
*props
[] = { NULL
, NULL
};
987 pool_value_t val
= POOL_VALUE_INITIALIZER
;
988 pool_component_t
**cs
= NULL
;
993 pool_value_set_bool(props
[0], PO_TRUE
);
994 if (pool_value_set_name(props
[0], "cpu.pinned") != PO_SUCCESS
)
997 if ((cs
= pool_query_resource_components(TO_CONF(TO_ELEM(res
)), res
,
998 &ncompelem
, props
)) != NULL
) {
1003 return (PO_SUCCESS
);
1007 * resource_get_min() updates min with the minimum size of the supplied
1010 * Returns PO_SUCCESS/PO_FAIL
1013 resource_get_min(const pool_resource_t
*res
, uint64_t *min
)
1015 return (resource_get_common(res
, c_min_prop
, min
));
1019 * resource_get_max() updates max with the maximum size of the supplied
1022 * Returns PO_SUCCESS/PO_FAIL
1025 resource_get_max(const pool_resource_t
*res
, uint64_t *max
)
1027 return (resource_get_common(res
, c_max_prop
, max
));
1031 * TODO: This is pset specific
1033 * get_default_resource() returns the default resource for type of the supplied
1036 * Returns A pointer to the default resource of the same type as the supplied
1039 const pool_resource_t
*
1040 get_default_resource(const pool_resource_t
*res
)
1042 return (resource_by_sysid(TO_CONF(TO_ELEM(res
)), PS_NONE
,
1043 pool_elem_class_string(TO_ELEM(res
))));
1047 * resource_is_default() returns 1 if the supplied resource is the default
1048 * resource for it's type.
1051 resource_is_default(const pool_resource_t
*res
)
1054 return (get_default_resource(res
) == res
);
1058 * resource_is_system() determines if the resource is a system resource.
1061 resource_is_system(const pool_resource_t
*res
)
1063 return (res
->pr_is_system(res
));
1068 * resource_can_associate() determines if it is possible to associate
1069 * with the supplied resource.
1072 resource_can_associate(const pool_resource_t
*res
)
1074 return (res
->pr_can_associate(res
));
1078 * Common code to get an int64 property.
1079 * Unfortunately (-1) is a valid psetid, so we'll return (-2) in case of
1083 elem_get_expected_int64(const pool_elem_t
*elem
, const char *name
)
1086 pool_value_t val
= POOL_VALUE_INITIALIZER
;
1088 if (pool_get_ns_property(elem
, name
, &val
) != POC_INT
) {
1089 return (POOL_SYSID_BAD
);
1091 (void) pool_value_get_int64(&val
, &val64
);
1097 * The following returns a malloc'ed string which must be free'd by the
1101 elem_get_expected_string(const pool_elem_t
*elem
, const char *name
)
1103 pool_value_t val
= POOL_VALUE_INITIALIZER
;
1106 if (pool_get_ns_property(elem
, name
, &val
) != POC_STRING
) {
1109 (void) pool_value_get_string(&val
, (const char **)&retval
);
1110 retval
= strdup(retval
);
1115 * elem_get_sysid() returns the sys_id for the supplied elem.
1118 elem_get_sysid(const pool_elem_t
*elem
)
1120 return ((id_t
)elem_get_expected_int64(elem
, c_sys_prop
));
1124 * elem_get_name() returns the name for the supplied elem. Note that
1125 * it is the caller's responsibility to free this memory.
1128 elem_get_name(const pool_elem_t
*elem
)
1130 return (elem_get_expected_string(elem
, c_name
));
1134 * elem_is_default() returns 1 if the supplied elem is the default
1135 * elem for it's type.
1138 elem_is_default(const pool_elem_t
*res
)
1141 return (get_default_elem(res
) == res
);
1145 * Return B_TRUE if the element has the 'temporary' property set.
1148 elem_is_tmp(const pool_elem_t
*elem
)
1150 pool_value_t val
= POOL_VALUE_INITIALIZER
;
1153 if (pool_get_ns_property(elem
, "temporary", &val
) != POC_BOOL
)
1156 (void) pool_value_get_bool(&val
, &bval
);
1162 * get_default_elem() returns the default elem for type of the supplied
1165 * Returns A pointer to the default elem of the same type as the
1166 * supplied elem or NULL on error. Trying to access the default elem
1167 * for a type of element which doesn't support the notion of default
1171 get_default_elem(const pool_elem_t
*pe
)
1173 pool_result_set_t
*rs
;
1174 pool_value_t
*props
[] = { NULL
, NULL
};
1175 pool_value_t val
= POOL_VALUE_INITIALIZER
;
1177 const pool_elem_t
*pe_default
;
1180 if ((cb
= alloc_char_buf(CB_DEFAULT_LEN
)) == NULL
) {
1183 if (set_char_buf(cb
, "%s.default", pool_elem_class_string(pe
)) !=
1188 if (pool_value_set_name(props
[0], cb
->cb_buf
) != PO_SUCCESS
) {
1193 pool_value_set_bool(props
[0], PO_TRUE
);
1195 if ((rs
= pool_exec_query(TO_CONF(pe
), NULL
, NULL
,
1196 PEC_QRY_ELEM(pe
), props
)) == NULL
) {
1197 pool_seterror(POE_INVALID_CONF
);
1200 if (pool_rs_count(rs
) != 1) {
1201 (void) pool_rs_close(rs
);
1202 pool_seterror(POE_INVALID_CONF
);
1206 pe_default
= rs
->prs_next(rs
);
1207 (void) pool_rs_close(rs
);
1208 return (pe_default
);
1212 * is_a_known_prefix() determines if the supplied prop_name is a known
1213 * name for the supplied class.
1215 * Returns a pointer to the prefix if it is found or NULL
1218 is_a_known_prefix(pool_elem_class_t
class, const char *prop_name
)
1226 len
= strlen(pool_elem_class_name
[class]);
1227 if (strncmp(prop_name
, pool_elem_class_name
[class], len
) == 0 &&
1228 prop_name
[len
] == '.' || strcmp(prop_name
, c_type
) == 0)
1229 return (pool_elem_class_name
[class]);
1233 for (i
= 0; i
< sizeof (pool_resource_elem_class_name
) /
1234 sizeof (pool_resource_elem_class_name
[0]); i
++) {
1235 len
= strlen(pool_resource_elem_class_name
[i
]);
1236 if (strncmp(prop_name
,
1237 pool_resource_elem_class_name
[i
], len
) == 0 &&
1238 prop_name
[len
] == '.' ||
1239 strcmp(prop_name
, c_type
) == 0)
1240 return (pool_resource_elem_class_name
[i
]);
1244 for (i
= 0; i
< sizeof (pool_component_elem_class_name
) /
1245 sizeof (pool_component_elem_class_name
[0]); i
++) {
1246 len
= strlen(pool_component_elem_class_name
[i
]);
1247 if (strncmp(prop_name
,
1248 pool_component_elem_class_name
[i
], len
) == 0 &&
1249 prop_name
[len
] == '.' ||
1250 strcmp(prop_name
, c_type
) == 0)
1251 return (pool_component_elem_class_name
[i
]);
1262 pool_elem_class_string(const pool_elem_t
*pe
)
1264 switch (pool_elem_class(pe
)) {
1267 return (pool_elem_class_name
[pool_elem_class(pe
)]);
1270 return (pool_resource_elem_class_name
1271 [pool_resource_elem_class(pe
)]);
1273 return (pool_component_elem_class_name
1274 [pool_component_elem_class(pe
)]);
1276 return (pool_elem_class_name
[PEC_INVALID
]);
1281 pool_resource_type_string(pool_resource_elem_class_t type
)
1283 return (pool_resource_elem_class_name
[type
]);
1287 pool_component_type_string(pool_component_elem_class_t type
)
1289 return (pool_component_elem_class_name
[type
]);
1293 * resource_by_sysid() finds a resource from it's supplied sysid and type.
1295 * Returns a pointer to the resource or NULL if it doesn't exist.
1298 resource_by_sysid(const pool_conf_t
*conf
, id_t sysid
, const char *type
)
1300 pool_value_t
*props
[] = { NULL
, NULL
, NULL
};
1301 pool_resource_t
**resources
= NULL
;
1302 pool_resource_t
*retval
= NULL
;
1305 pool_value_t val0
= POOL_VALUE_INITIALIZER
;
1306 pool_value_t val1
= POOL_VALUE_INITIALIZER
;
1311 if (pool_value_set_string(props
[0], type
) != PO_SUCCESS
||
1312 pool_value_set_name(props
[0], c_type
) != PO_SUCCESS
)
1315 if ((cb
= alloc_char_buf(CB_DEFAULT_LEN
)) == NULL
) {
1318 if (set_char_buf(cb
, "%s.sys_id", type
) != PO_SUCCESS
) {
1322 if (pool_value_set_name(props
[1], cb
->cb_buf
) != PO_SUCCESS
) {
1327 pool_value_set_int64(props
[1], sysid
);
1329 resources
= pool_query_resources(conf
, &nelem
, props
);
1331 if (resources
!= NULL
) {
1332 retval
= resources
[0];
1339 pool_elem_class_from_string(const char *type
)
1343 for (i
= 0; i
< sizeof (pool_elem_class_name
) /
1344 sizeof (pool_elem_class_name
[0]); i
++) {
1345 if (strcmp(pool_elem_class_name
[i
], type
) == 0)
1348 if (i
== sizeof (pool_elem_class_name
) /
1349 sizeof (pool_elem_class_name
[0]))
1350 return (PEC_INVALID
);
1351 return ((pool_elem_class_t
)i
);
1354 pool_resource_elem_class_t
1355 pool_resource_elem_class_from_string(const char *type
)
1359 for (i
= 0; i
< sizeof (pool_resource_elem_class_name
) /
1360 sizeof (pool_resource_elem_class_name
[0]); i
++) {
1361 if (strcmp(pool_resource_elem_class_name
[i
], type
) == 0)
1364 if (i
== sizeof (pool_resource_elem_class_name
) /
1365 sizeof (pool_resource_elem_class_name
[0]))
1366 return (PREC_INVALID
);
1367 return ((pool_resource_elem_class_t
)i
);
1370 pool_component_elem_class_t
1371 pool_component_elem_class_from_string(const char *type
)
1375 for (i
= 0; i
< sizeof (pool_component_elem_class_name
) /
1376 sizeof (pool_component_elem_class_name
[0]); i
++) {
1377 if (strcmp(pool_component_elem_class_name
[i
], type
) == 0)
1380 if (i
== sizeof (pool_component_elem_class_name
) /
1381 sizeof (pool_component_elem_class_name
[0]))
1382 return (PCEC_INVALID
);
1383 return ((pool_component_elem_class_t
)i
);
1387 * pool_resource_type_list() populates the supplied array of pointers
1388 * with the names of the available resource types on this system.
1391 pool_resource_type_list(const char **types
, uint_t
*numtypes
)
1394 uint_t maxnum
= *numtypes
;
1396 *numtypes
= pool_get_provider_count();
1399 for (i
= 0, j
= 0; i
< sizeof (pool_resource_elem_ctl
) /
1400 sizeof (pool_resource_elem_ctl
[0]) && j
< maxnum
; i
++) {
1401 if (pool_resource_elem_ctl
[i
] != NULL
)
1402 types
[j
++] = pool_resource_elem_class_name
[i
];
1405 return (PO_SUCCESS
);
1409 * Return the system element for the supplied conf.
1410 * NULL is returned if an error is detected and the error code is updated
1411 * to indicate the cause of the error.
1414 pool_conf_system(const pool_conf_t
*conf
)
1416 pool_elem_t
*system
;
1417 pool_result_set_t
*rs
;
1419 if ((rs
= pool_exec_query(conf
, NULL
, NULL
, PEC_QRY_SYSTEM
, NULL
)) ==
1421 pool_seterror(POE_INVALID_CONF
);
1424 /* There should only be one system record */
1425 if (pool_rs_count(rs
) != 1) {
1426 pool_seterror(POE_INVALID_CONF
);
1427 (void) pool_rs_close(rs
);
1430 system
= rs
->prs_next(rs
);
1431 (void) pool_rs_close(rs
);
1432 return (pool_elem_system(system
));
1436 pool_elem_system(const pool_elem_t
*pe
)
1438 if (pe
->pe_class
!= PEC_SYSTEM
) {
1439 pool_seterror(POE_BADPARAM
);
1442 return ((pool_system_t
*)pe
);
1446 pool_elem_pool(const pool_elem_t
*pe
)
1448 if (pe
->pe_class
!= PEC_POOL
) {
1449 pool_seterror(POE_BADPARAM
);
1452 return ((pool_t
*)pe
);
1456 pool_elem_res(const pool_elem_t
*pe
)
1458 if (pe
->pe_class
!= PEC_RES_COMP
&&
1459 pool_elem_class(pe
) != PEC_RES_AGG
) {
1460 pool_seterror(POE_BADPARAM
);
1463 return ((pool_resource_t
*)pe
);
1467 pool_elem_comp(const pool_elem_t
*pe
)
1469 if (pe
->pe_class
!= PEC_COMP
) {
1470 pool_seterror(POE_BADPARAM
);
1473 return ((pool_component_t
*)pe
);
1477 * qsort_elem_compare() is used for qsort elemement comparison.
1479 * Returns see qsort(3c)
1482 qsort_elem_compare(const void *a
, const void *b
)
1484 const pool_elem_t
*e1
= *(const pool_elem_t
**)a
;
1485 const pool_elem_t
*e2
= *(const pool_elem_t
**)b
;
1488 * Special case for handling name changes on default elements
1489 * If both elements are default elements then always return 0
1491 if (pool_elem_same_class(e1
, e2
) == PO_TRUE
&&
1492 (elem_is_default(e1
) && elem_is_default(e2
)))
1495 return (pool_elem_compare_name(e1
, e2
));
1499 * Dynamic character buffers.
1503 * Resize the supplied character buffer to the new size.
1506 resize_char_buf(char_buf_t
*cb
, size_t size
)
1510 if ((re_cb
= realloc(cb
->cb_buf
, size
)) == NULL
) {
1511 pool_seterror(POE_SYSTEM
);
1514 /* If inital allocation, make sure buffer is zeroed */
1515 if (cb
->cb_buf
== NULL
)
1516 (void) memset(re_cb
, 0, sizeof (re_cb
));
1517 /* If resized smaller, make sure buffer NULL terminated */
1518 if (size
< cb
->cb_size
)
1522 return (PO_SUCCESS
);
1526 * Allocate a new char_buf_t structure. If there isn't enough memory, return
1527 * NULL. Initialise the new char_buf_t to 0 and then call resize_char_buf
1528 * to initialise the character buffer. Return a pointer to the new
1529 * char_buf_t if the operation succeeds.
1532 alloc_char_buf(size_t size
)
1536 if ((cb
= malloc(sizeof (char_buf_t
))) == NULL
) {
1537 pool_seterror(POE_SYSTEM
);
1540 (void) memset(cb
, 0, sizeof (char_buf_t
));
1542 if (resize_char_buf(cb
, size
+ 1) == PO_FAIL
) {
1550 * Free the character buffer and then free the char_buf_t.
1553 free_char_buf(char_buf_t
*cb
)
1555 free((void *)cb
->cb_buf
);
1560 * Set the character buffer to the supplied data. The user supplies a printf
1561 * like format string and then an appropriate number of parameters for the
1562 * specified format. The character buffer is automatically resized to fit
1563 * the data as determined by resize_char_buf.
1567 set_char_buf(char_buf_t
*cb
, const char *fmt
, ...)
1573 if ((new_size
= vsnprintf(cb
->cb_buf
, cb
->cb_size
, fmt
, ap
)) >=
1575 if (resize_char_buf(cb
, new_size
+ 1) != PO_SUCCESS
) {
1576 pool_seterror(POE_SYSTEM
);
1579 (void) vsnprintf(cb
->cb_buf
, cb
->cb_size
, fmt
, ap
);
1582 return (PO_SUCCESS
);
1586 * Append the supplied data to the character buffer. The user supplies a printf
1587 * like format string and then an appropriate number of parameters for the
1588 * specified format. The character buffer is automatically resized to fit
1589 * the data as determined by resize_char_buf.
1593 append_char_buf(char_buf_t
*cb
, const char *fmt
, ...)
1600 if (cb
->cb_buf
!= NULL
)
1601 old_len
= strlen(cb
->cb_buf
);
1603 new_len
= vsnprintf(size_buf
, sizeof (size_buf
), fmt
, ap
);
1604 if (new_len
+ old_len
>= cb
->cb_size
) {
1605 if (resize_char_buf(cb
, old_len
+ new_len
+ 1) !=
1607 pool_seterror(POE_SYSTEM
);
1612 * Resized the buffer to the right size, now append the new data
1614 (void) vsnprintf(&cb
->cb_buf
[old_len
], cb
->cb_size
- old_len
, fmt
, ap
);
1616 return (PO_SUCCESS
);
1620 * Return the class for the supplied elem.
1621 * If the return is PEC_INVALID, the error code will be set to reflect cause.
1624 pool_elem_class(const pool_elem_t
*elem
)
1626 return (elem
->pe_class
);
1631 * Return the resource class for the supplied elem.
1633 pool_resource_elem_class_t
1634 pool_resource_elem_class(const pool_elem_t
*elem
)
1636 return (elem
->pe_resource_class
);
1640 * Return the component class for the supplied elem.
1642 pool_component_elem_class_t
1643 pool_component_elem_class(const pool_elem_t
*elem
)
1645 return (elem
->pe_component_class
);
1649 pool_get_pair(const pool_elem_t
*pe
)
1651 return (pe
->pe_pair
);
1655 pool_set_pair(pool_elem_t
*pe1
, pool_elem_t
*pe2
)
1661 pool_validate_resource(const pool_conf_t
*conf
, const char *type
,
1662 const char *prop
, int64_t delta
)
1666 uint64_t available
, required
, uval
;
1668 pool_resource_t
**rl
;
1669 pool_value_t val
= POOL_VALUE_INITIALIZER
;
1670 pool_value_t val1
= POOL_VALUE_INITIALIZER
;
1671 pool_value_t
*pvals
[] = { NULL
, NULL
};
1673 if (strcmp(prop
, c_min_prop
) && strcmp(prop
, c_max_prop
)) {
1674 pool_seterror(POE_BADPARAM
);
1679 (void) pool_value_set_string(&val
, type
);
1680 (void) pool_value_set_name(&val
, c_type
);
1683 * Check that there are available resources on this
1684 * system for this configuration to be applied. Find
1685 * each resource type and then find all resources of
1686 * each type and total ".min". Find all available
1687 * resources and ensure >= total min.
1693 if ((rl
= (pool_query_resources(conf
, &nelem
, pvals
))) == NULL
)
1696 for (i
= 0; i
< nelem
; i
++) {
1697 if (pool_get_ns_property(TO_ELEM(rl
[i
]), prop
,
1698 &val1
) == POC_INVAL
||
1699 pool_value_get_uint64(&val1
, &uval
) != PO_SUCCESS
) {
1704 * Watch out for overflow
1706 if (required
+ uval
< required
) {
1707 required
= UINT64_MAX
;
1713 if (conf_is_dynamic(conf
) == PO_TRUE
) {
1714 dyn
= (pool_conf_t
*)conf
;
1717 if ((dyn
= pool_conf_alloc()) == NULL
)
1719 if (pool_conf_open(dyn
, pool_dynamic_location(), PO_RDONLY
) !=
1721 pool_conf_free(dyn
);
1724 if ((rl
= (pool_query_resources(dyn
, &nelem
, pvals
))) ==
1726 (void) pool_conf_close(dyn
);
1727 pool_conf_free(dyn
);
1731 for (i
= 0; i
< nelem
; i
++) {
1732 if (pool_get_ns_property(TO_ELEM(rl
[i
]), c_size_prop
,
1733 &val1
) == POC_INVAL
||
1734 pool_value_get_uint64(&val1
, &uval
) != PO_SUCCESS
) {
1737 (void) pool_conf_close(dyn
);
1738 pool_conf_free(dyn
);
1746 (void) pool_conf_close(dyn
);
1747 pool_conf_free(dyn
);
1749 if (strcmp(prop
, c_min_prop
) == 0) {
1750 if (available
< required
) {
1751 pool_seterror(POE_INVALID_CONF
);
1755 if (available
> required
) {
1756 pool_seterror(POE_INVALID_CONF
);
1760 return (PO_SUCCESS
);
1764 * If _libpool_debug is set, printf the debug message to stderr with an
1765 * appropriate prefix in front of it.
1768 do_dprintf(const char *format
, va_list ap
)
1770 if (_libpool_debug
) {
1771 (void) fputs("libpool DEBUG: ", stderr
);
1772 (void) vfprintf(stderr
, format
, ap
);
1778 dprintf(const char *format
, ...)
1780 if (_libpool_debug
) {
1782 va_start(alist
, format
);
1783 do_dprintf(format
, alist
);
1789 * log_alloc() allocates a new, empty transaction log.
1791 * Returns a pointer to the new log or NULL on failure.
1794 log_alloc(pool_conf_t
*conf
)
1798 if ((l
= calloc(1, sizeof (log_t
))) == NULL
) {
1799 pool_seterror(POE_SYSTEM
);
1804 if ((l
->l_sentinel
= log_item_alloc(l
, 0, NULL
))
1807 pool_seterror(POE_SYSTEM
);
1810 l
->l_sentinel
->li_next
= l
->l_sentinel
;
1811 l
->l_sentinel
->li_prev
= l
->l_sentinel
;
1817 * log_free() reclaims the resources associated with a transaction log.
1822 (void) log_walk(l
, log_item_free
);
1823 (void) log_item_free(l
->l_sentinel
);
1827 * log_empty() removes all items from a transaction log. It is the
1828 * users responsibility to ensure that any resources associated with
1829 * an item are reclaimed before this function is invoked.
1834 (void) log_walk(l
, log_item_free
);
1838 * log_walk() visits each log item in turn and executes the supplied action
1839 * using the item as a parameter. If no action is supplied, then the item
1840 * uses it's own stored action.
1842 * Returns PO_SUCCESS/PO_FAIL
1845 log_walk(log_t
*l
, log_item_action_t action
)
1847 log_item_t
*li
, *li_next
;
1849 li
= l
->l_sentinel
->li_next
;
1850 while (li
!= l
->l_sentinel
) {
1851 li_next
= li
->li_next
;
1852 if ((action(li
)) != PO_SUCCESS
)
1856 return (PO_SUCCESS
);
1860 * log_reverse_walk() visits each log item in turn (in reverse order)
1861 * and executes the supplied action using the item as a parameter.
1863 * Returns PO_SUCCESS/PO_FAIL
1866 log_reverse_walk(log_t
*l
, log_item_action_t action
)
1868 log_item_t
*li
, *li_prev
;
1870 li
= l
->l_sentinel
->li_prev
;
1871 while (li
!= l
->l_sentinel
) {
1872 li_prev
= li
->li_prev
;
1873 if ((action(li
)) != PO_SUCCESS
)
1877 return (PO_SUCCESS
);
1881 * log_size() returns the size of the log, i.e. the number of items pending in
1890 for (li
= l
->l_sentinel
->li_next
; li
!= l
->l_sentinel
; li
= li
->li_next
)
1896 * log_append() allocates a new log item to hold the supplied details and
1897 * appends the newly created item to the supplied log.
1899 * Returns PO_SUCCESS/PO_FAIL
1902 log_append(log_t
*l
, int op
, void *details
)
1906 if ((li
= log_item_alloc(l
, op
, details
)) == NULL
) {
1907 l
->l_state
= LS_UNDO
;
1913 li
->li_prev
= l
->l_sentinel
->li_prev
;
1914 li
->li_next
= l
->l_sentinel
;
1915 l
->l_sentinel
->li_prev
->li_next
= li
;
1916 l
->l_sentinel
->li_prev
= li
;
1917 return (PO_SUCCESS
);
1921 * log_item_alloc() allocates a new transaction log item. The item should be
1922 * used to store details about a transaction which may need to be undone if
1923 * commit processing fails.
1925 * Returns a pointer to a new transaction log item or NULL.
1928 log_item_alloc(log_t
*l
, int op
, void *details
)
1932 if ((li
= malloc(sizeof (log_item_t
))) == NULL
) {
1933 pool_seterror(POE_SYSTEM
);
1937 (void) memset(li
, 0, sizeof (log_item_t
));
1940 li
->li_details
= details
;
1941 li
->li_state
= LS_DO
;
1947 * log_item_free() reclaims the resources associated with a log_item_t.
1950 log_item_free(log_item_t
*li
)
1952 li
->li_prev
->li_next
= li
->li_next
;
1953 li
->li_next
->li_prev
= li
->li_prev
;
1955 return (PO_SUCCESS
);
1959 * atom_string() checks the string table to see if a string is already
1960 * stored. If it is, return a pointer to it. If not, duplicate the
1961 * string and return a pointer to the duplicate.
1964 atom_string(const char *s
)
1969 * atom_init() must have completed successfully
1972 (void) mutex_lock(&_atom_lock
);
1973 if ((atom
= dict_get(_pv_atoms
, s
)) == NULL
) {
1974 if ((atom
= calloc(1, sizeof (atom_t
))) == NULL
) {
1975 pool_seterror(POE_SYSTEM
);
1976 (void) mutex_unlock(&_atom_lock
);
1979 if ((atom
->a_string
= strdup(s
)) == NULL
) {
1980 (void) mutex_unlock(&_atom_lock
);
1982 pool_seterror(POE_SYSTEM
);
1985 (void) dict_put(_pv_atoms
, atom
->a_string
, atom
);
1988 (void) mutex_unlock(&_atom_lock
);
1989 return (atom
->a_string
);
1993 * atom_free() decrements the reference count for the supplied
1994 * string. If the reference count reaches zero, then the atom is
1998 atom_free(const char *s
)
2002 (void) mutex_lock(&_atom_lock
);
2003 if ((atom
= dict_get(_pv_atoms
, s
)) != NULL
) {
2004 if (--atom
->a_count
== 0) {
2005 (void) dict_remove(_pv_atoms
, s
);
2006 free(atom
->a_string
);
2010 (void) mutex_unlock(&_atom_lock
);
2015 * log_item_dprintf() prints the contents of the supplied log item using the
2016 * pools dprintf() trace mechanism.
2018 * Returns PO_SUCCESS
2021 log_item_dprintf(log_item_t
*li
)
2023 dprintf("LOGDUMP: %d operation, %p\n", li
->li_op
, li
->li_details
);
2027 * log_item_dprintf() prints the contents of the supplied log item using the
2028 * pools dprintf() trace mechanism.
2030 * Returns PO_SUCCESS
2033 pool_elem_dprintf(const pool_elem_t
*pe
)
2035 if (pool_elem_class(pe
) != PEC_COMP
) {
2036 const char *name
= elem_get_name(pe
);
2037 dprintf("element type: %s name: %s\n",
2038 pool_elem_class_string(pe
), name
);
2041 id_t sys_id
= elem_get_sysid(pe
);
2042 dprintf("element type: %s sys_id: %d\n",
2043 pool_elem_class_string(pe
), sys_id
);