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]
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Copyright (c) 2015, Joyent, Inc. All rights reserved.
39 #include <sys/types.h>
42 #include <repcache_protocol.h>
45 #include <configd_exit.h>
55 * iter locks, in ID order
56 * entity locks, in ID order
58 * (any iter/entity locks)
59 * backend locks (NORMAL, then NONPERSIST)
61 * children's rc_node lock
65 * * only one node may be grabbed while holding a bucket lock
67 * leaf locks: (no other locks may be aquired while holding one)
73 * Returns the minimum size for a structure of type 't' such
74 * that it is safe to access field 'f'.
76 #define offsetofend(t, f) (offsetof(t, f) + sizeof (((t *)0)->f))
79 * We want MUTEX_HELD, but we also want pthreads. So we're stuck with this
80 * for the native build, at least until the build machines can catch up
81 * with the latest version of MUTEX_HELD() in <synch.h>.
83 #if defined(NATIVE_BUILD)
85 #define MUTEX_HELD(m) _mutex_held((mutex_t *)(m))
89 * Maximum levels of composition.
91 #define COMPOSITION_DEPTH 2
93 #define CONFIGD_CORE "core.%f.%t.%p"
95 #define bad_error(f, e) \
96 uu_panic("%s:%d: %s() returned bad error %d. Aborting.\n", \
97 __FILE__, __LINE__, f, e);
99 typedef enum backend_type
{
100 BACKEND_TYPE_NORMAL
= 0,
101 BACKEND_TYPE_NONPERSIST
,
102 BACKEND_TYPE_TOTAL
/* backend use only */
106 * pre-declare rc_* types
108 typedef struct rc_node rc_node_t
;
109 typedef struct rc_snapshot rc_snapshot_t
;
110 typedef struct rc_snaplevel rc_snaplevel_t
;
113 * notification layer -- protected by rc_pg_notify_lock
115 typedef struct rc_notify_info rc_notify_info_t
;
116 typedef struct rc_notify_delete rc_notify_delete_t
;
118 #define RC_NOTIFY_MAX_NAMES 4 /* enough for now */
120 typedef struct rc_notify
{
121 uu_list_node_t rcn_list_node
;
123 rc_notify_info_t
*rcn_info
;
124 rc_notify_delete_t
*rcn_delete
;
127 struct rc_notify_delete
{
128 rc_notify_t rnd_notify
;
129 char rnd_fmri
[REP_PROTOCOL_FMRI_LEN
];
132 struct rc_notify_info
{
133 uu_list_node_t rni_list_node
;
134 rc_notify_t rni_notify
;
135 const char *rni_namelist
[RC_NOTIFY_MAX_NAMES
];
136 const char *rni_typelist
[RC_NOTIFY_MAX_NAMES
];
140 pthread_cond_t rni_cv
;
142 #define RC_NOTIFY_ACTIVE 0x00000001
143 #define RC_NOTIFY_DRAIN 0x00000002
144 #define RC_NOTIFY_EMPTYING 0x00000004
146 typedef struct rc_node_pg_notify
{
147 uu_list_node_t rnpn_node
;
150 } rc_node_pg_notify_t
;
157 * The 'key' for the main object hash. main_id is the main object
158 * identifier. The rl_ids array contains:
163 * instance {service_id}
164 * snapshot {service_id, instance_id}
165 * snaplevel {service_id, instance_id, name_id, snapshot_id}
166 * propertygroup {service_id, (instance_id or 0), (name_id or 0),
167 * (snapshot_id or 0), (l_id or 0)}
168 * property {service_id, (instance_id or 0), (name_id or 0),
169 * (snapshot_id or 0), (l_id or 0), pg_id, gen_id}
172 #define ID_INSTANCE 1
174 #define ID_SNAPSHOT 3
179 typedef struct rc_node_lookup
{
180 uint16_t rl_type
; /* REP_PROTOCOL_ENTITY_* */
181 uint16_t rl_backend
; /* BACKEND_TYPE_* */
182 uint32_t rl_main_id
; /* primary identifier */
183 uint32_t rl_ids
[MAX_IDS
]; /* context */
190 rc_node_lookup_t rn_id
; /* must be first */
195 * type-specific state
196 * (if space becomes an issue, these can become a union)
200 * Used by instances, snapshots, and "composed property groups" only.
201 * These are the entities whose properties should appear composed when
202 * this entity is traversed by a composed iterator. 0 is the top-most
203 * entity, down to COMPOSITION_DEPTH - 1.
205 rc_node_t
*rn_cchain
[COMPOSITION_DEPTH
];
208 * used by property groups only
213 uu_list_t
*rn_pg_notify_list
; /* prot by rc_pg_notify_lock */
214 rc_notify_t rn_notify
; /* prot by rc_pg_notify_lock */
217 * used by properties only
219 rep_protocol_value_type_t rn_valtype
;
220 const char *rn_values
; /* protected by rn_lock */
221 size_t rn_values_count
; /* protected by rn_lock */
222 size_t rn_values_size
; /* protected by rn_lock */
225 * used by snapshots only
227 uint32_t rn_snapshot_id
;
228 rc_snapshot_t
*rn_snapshot
; /* protected by rn_lock */
231 * used by snaplevels only
233 rc_snaplevel_t
*rn_snaplevel
;
238 pthread_mutex_t rn_lock
;
239 pthread_cond_t rn_cv
;
241 uint32_t rn_refs
; /* client reference count */
242 uint32_t rn_erefs
; /* ephemeral ref count */
243 uint32_t rn_other_refs
; /* atomic refcount */
244 uint32_t rn_other_refs_held
; /* for 1->0 transitions */
246 uu_list_t
*rn_children
;
247 uu_list_node_t rn_sibling_node
;
249 rc_node_t
*rn_parent
; /* set if on child list */
250 rc_node_t
*rn_former
; /* next former node */
251 rc_node_t
*rn_parent_ref
; /* reference count target */
255 * external state (protected by hash chain lock)
257 rc_node_t
*rn_hash_next
;
263 * RC_NODE_CHILDREN_CHANGING
264 * RC_NODE_CREATING_CHILD
265 * RC_NODE_USING_PARENT
268 * RC_NODE_USING_PARENT is special, because it lets you proceed up the tree,
269 * in the reverse of the usual locking order. Because of this, there are
270 * limitations on what you can do while holding it. While holding
271 * RC_NODE_USING_PARENT, you may:
272 * bump or release your parent's reference count
273 * access fields in your parent
274 * hold RC_NODE_USING_PARENT in the parent, proceeding recursively.
276 * If you are only holding *one* node's RC_NODE_USING_PARENT, and:
277 * you are *not* proceeding recursively, you can hold your
278 * immediate parent's RC_NODE_CHILDREN_CHANGING flag.
279 * you hold your parent's RC_NODE_CHILDREN_CHANGING flag, you can add
280 * RC_NODE_IN_TX to your flags.
281 * you want to grab a flag in your parent, you must lock your parent,
282 * lock yourself, drop RC_NODE_USING_PARENT, unlock yourself,
283 * then proceed to manipulate the parent.
285 #define RC_NODE_CHILDREN_CHANGING 0x00000001 /* child list in flux */
286 #define RC_NODE_HAS_CHILDREN 0x00000002 /* child list is accurate */
288 #define RC_NODE_IN_PARENT 0x00000004 /* I'm in my parent's list */
289 #define RC_NODE_USING_PARENT 0x00000008 /* parent ptr in use */
290 #define RC_NODE_CREATING_CHILD 0x00000010 /* a create is in progress */
291 #define RC_NODE_IN_TX 0x00000020 /* a tx is in progess */
293 #define RC_NODE_OLD 0x00000400 /* out-of-date object */
294 #define RC_NODE_ON_FORMER 0x00000800 /* on an rn_former list */
296 #define RC_NODE_PARENT_REF 0x00001000 /* parent_ref in use */
297 #define RC_NODE_UNREFED 0x00002000 /* unref processing active */
298 #define RC_NODE_DYING 0x00004000 /* node is being deleted */
299 #define RC_NODE_DEAD 0x00008000 /* node has been deleted */
302 * RC_NODE_DEAD means that the node no longer represents data in the
303 * backend, and we should return _DELETED errors to clients who try to use
304 * it. Very much like a zombie process.
306 * RC_NODE_OLD also means that the node no longer represents data in the
307 * backend, but it's ok for clients to access it because we've loaded all of
308 * the children. (This only happens for transactional objects such as
309 * property groups and snapshots, where we guarantee a stable view once
310 * a reference is obtained.) When all client references are destroyed,
311 * however, the node should be destroyed.
313 * Though RC_NODE_DEAD is set by the rc_node_delete() code, it is also set
314 * by rc_node_no_client_refs() for RC_NODE_OLD nodes not long before
318 #define RC_NODE_DYING_FLAGS \
319 (RC_NODE_CHILDREN_CHANGING | RC_NODE_IN_TX | RC_NODE_DYING | \
320 RC_NODE_CREATING_CHILD)
322 #define RC_NODE_WAITING_FLAGS \
323 (RC_NODE_DYING_FLAGS | RC_NODE_USING_PARENT)
326 #define NODE_LOCK(n) (void) pthread_mutex_lock(&(n)->rn_lock)
327 #define NODE_UNLOCK(n) (void) pthread_mutex_unlock(&(n)->rn_lock)
330 typedef enum rc_auth_state
{
331 RC_AUTH_UNKNOWN
= 0, /* No checks done yet. */
332 RC_AUTH_FAILED
, /* Authorization checked & failed. */
333 RC_AUTH_PASSED
/* Authorization succeeded. */
337 * Some authorization checks are performed in rc_node_setup_tx() in
338 * response to the REP_PROTOCOL_PROPERTYGRP_TX_START message. Other checks
339 * must wait until the actual transaction operations are received in the
340 * REP_PROTOCOL_PROPERTYGRP_TX_COMMIT message. This second set of checks
341 * is performed in rc_tx_commit(). rnp_auth_string and rnp_authorized in
342 * the following structure are used to hold the results of the
343 * authorization checking done in rc_node_setup_tx() for later use by
346 * In client.c transactions are represented by rc_node_ptr structures which
347 * point to a property group rc_node_t. Thus, this is an appropriate place
348 * to hold authorization state.
350 typedef struct rc_node_ptr
{
352 const char *rnp_auth_string
; /* authorization string */
353 rc_auth_state_t rnp_authorized
; /* transaction pre-auth rslt. */
354 char rnp_deleted
; /* object was deleted */
357 #define NODE_PTR_NOT_HELD(npp) \
358 ((npp)->rnp_node == NULL || !MUTEX_HELD(&(npp)->rnp_node->rn_lock))
360 typedef int rc_iter_filter_func(rc_node_t
*, void *);
362 typedef struct rc_node_iter
{
363 rc_node_t
*rni_parent
;
364 int rni_clevel
; /* index into rni_parent->rn_cchain[] */
365 rc_node_t
*rni_iter_node
;
366 uu_list_walk_t
*rni_iter
;
372 rc_iter_filter_func
*rni_filter
;
373 void *rni_filter_arg
;
378 uint32_t rni_offset
; /* next value offset */
379 uint32_t rni_last_offset
; /* previous value offset */
382 typedef struct rc_node_tx
{
383 rc_node_ptr_t rnt_ptr
;
384 int rnt_authorized
; /* No need to check anymore. */
388 typedef struct cache_bucket
{
389 pthread_mutex_t cb_lock
;
392 char cb_pad
[64 - sizeof (pthread_mutex_t
) -
393 2 * sizeof (rc_node_t
*)];
397 * tx_commit_data_tx is an opaque structure which is defined in object.c.
398 * It contains the data of the transaction that is to be committed.
399 * Accessor functions in object.c allow other modules to retrieve
402 typedef struct tx_commit_data tx_commit_data_t
;
410 pthread_mutex_t rs_lock
;
411 pthread_cond_t rs_cv
;
414 uint32_t rs_refcnt
; /* references from rc_nodes */
415 uint32_t rs_childref
; /* references to children */
417 rc_snaplevel_t
*rs_levels
; /* list of levels */
418 rc_snapshot_t
*rs_hash_next
;
420 #define RC_SNAPSHOT_FILLING 0x00000001 /* rs_levels changing */
421 #define RC_SNAPSHOT_READY 0x00000002
422 #define RC_SNAPSHOT_DEAD 0x00000004 /* no resources */
424 typedef struct rc_snaplevel_pgs
{
427 } rc_snaplevel_pgs_t
;
429 struct rc_snaplevel
{
430 rc_snapshot_t
*rsl_parent
;
431 uint32_t rsl_level_num
;
432 uint32_t rsl_level_id
;
434 uint32_t rsl_service_id
;
435 uint32_t rsl_instance_id
;
437 const char *rsl_scope
;
438 const char *rsl_service
;
439 const char *rsl_instance
;
441 rc_snaplevel_t
*rsl_next
;
445 * Client layer -- the IDs fields must be first, in order for the search
446 * routines to work correctly.
448 enum repcache_txstate
{
451 REPCACHE_TX_COMMITTED
454 typedef struct repcache_entity
{
456 uu_avl_node_t re_link
;
457 uint32_t re_changeid
;
459 pthread_mutex_t re_lock
;
461 rc_node_ptr_t re_node
;
462 enum repcache_txstate re_txstate
; /* property groups only */
465 typedef struct repcache_iter
{
467 uu_avl_node_t ri_link
;
469 uint32_t ri_type
; /* result type */
471 pthread_mutex_t ri_lock
;
472 uint32_t ri_sequence
;
473 rc_node_iter_t
*ri_iter
;
476 typedef struct repcache_client
{
480 uint32_t rc_id
; /* must be first */
481 int rc_all_auths
; /* bypass auth checks */
482 uint32_t rc_debug
; /* debug flags */
483 pid_t rc_pid
; /* pid of opening process */
484 door_id_t rc_doorid
; /* a globally unique identifier */
485 int rc_doorfd
; /* our door's FD */
488 * Constants used for security auditing
490 * rc_adt_session points to the audit session data that is used for
491 * the life of the client. rc_adt_sessionid is the session ID that
492 * is initially assigned when the audit session is started. See
493 * start_audit_session() in client.c. This session id is used for
494 * audit events except when we are processing a set of annotated
495 * events. Annotated events use a separate session id so that they
496 * can be grouped. See set_annotation() in client.c.
498 adt_session_data_t
*rc_adt_session
; /* Session data. */
499 au_asid_t rc_adt_sessionid
; /* Main session ID for */
503 * client list linkage, protected by hash chain lock
505 uu_list_node_t rc_link
;
508 * notification information, protected by rc_node layer
510 rc_node_pg_notify_t rc_pg_notify
;
511 rc_notify_info_t rc_notify_info
;
514 * client_wait output, only usable by rc_notify_thr
516 rc_node_ptr_t rc_notify_ptr
;
519 * register sets, protected by rc_lock
521 uu_avl_t
*rc_entities
;
525 * Variables, protected by rc_lock
527 int rc_refcnt
; /* in-progress door calls */
528 int rc_flags
; /* see RC_CLIENT_* symbols below */
529 uint32_t rc_changeid
; /* used to make backups idempotent */
530 pthread_t rc_insert_thr
; /* single thread trying to insert */
531 pthread_t rc_notify_thr
; /* single thread waiting for notify */
532 pthread_cond_t rc_cv
;
533 pthread_mutex_t rc_lock
;
536 * Per-client audit information. These fields must be protected by
537 * rc_annotate_lock separately from rc_lock because they may need
538 * to be accessed from rc_node.c with an entity or iterator lock
539 * held, and those must be taken after rc_lock.
541 int rc_annotate
; /* generate annotation event if set */
542 const char *rc_operation
; /* operation for audit annotation */
543 const char *rc_file
; /* file name for audit annotation */
544 pthread_mutex_t rc_annotate_lock
;
547 /* Bit definitions for rc_flags. */
548 #define RC_CLIENT_DEAD 0x00000001
550 typedef struct client_bucket
{
551 pthread_mutex_t cb_lock
;
553 char ch_pad
[64 - sizeof (pthread_mutex_t
) - sizeof (uu_list_t
*)];
557 RC_PTR_TYPE_ENTITY
= 1,
561 typedef struct request_log_ptr
{
562 enum rc_ptr_type rlp_type
;
564 void *rlp_ptr
; /* repcache_{entity,iter}_t */
565 void *rlp_data
; /* rc_node, for ENTITY only */
571 * rl_start through rl_client cannot move without changing start_log()
573 typedef struct request_log_entry
{
577 uint32_t rl_clientid
;
578 repcache_client_t
*rl_client
;
579 enum rep_protocol_requestid rl_request
;
580 rep_protocol_responseid_t rl_response
;
582 request_log_ptr_t rl_ptrs
[MAX_PTRS
];
583 } request_log_entry_t
;
588 typedef enum thread_state
{
596 typedef struct thread_info
{
598 uu_list_node_t ti_node
; /* for list of all thread */
603 ucred_t
*ti_ucred
; /* for credential lookups */
604 int ti_ucred_read
; /* ucred holds current creds */
607 * per-thread state information, for debuggers
609 hrtime_t ti_lastchange
;
611 thread_state_t ti_state
;
612 thread_state_t ti_prev_state
;
614 repcache_client_t
*ti_active_client
;
615 request_log_entry_t ti_log
;
617 struct rep_protocol_request
*ti_client_request
;
618 repository_door_request_t
*ti_main_door_request
;
625 typedef struct backend_query backend_query_t
;
626 typedef struct backend_tx backend_tx_t
;
631 int create_connection(ucred_t
*cred
, repository_door_request_t
*rp
,
632 size_t rp_size
, int *out_fd
);
634 thread_info_t
*thread_self(void);
635 void thread_newstate(thread_info_t
*, thread_state_t
);
636 ucred_t
*get_ucred(void);
637 int ucred_is_privileged(ucred_t
*);
639 adt_session_data_t
*get_audit_session(void);
641 void configd_critical(const char *, ...);
642 void configd_vcritical(const char *, va_list);
643 void configd_info(const char *, ...);
645 extern int is_main_repository
;
646 extern int max_repository_backups
;
651 int setup_main_door(const char *);
656 int client_annotation_needed(char *, size_t, char *, size_t);
657 void client_annotation_finished(void);
658 int create_client(pid_t
, uint32_t, int, int *);
659 int client_init(void);
660 int client_is_privileged(void);
661 void log_enter(request_log_entry_t
*);
664 * rc_node.c, backend/cache interfaces (rc_node_t)
667 int rc_check_type_name(uint32_t, const char *);
669 void rc_node_ptr_free_mem(rc_node_ptr_t
*);
670 void rc_node_rele(rc_node_t
*);
671 rc_node_t
*rc_node_setup(rc_node_t
*, rc_node_lookup_t
*,
672 const char *, rc_node_t
*);
673 rc_node_t
*rc_node_setup_pg(rc_node_t
*, rc_node_lookup_t
*, const char *,
674 const char *, uint32_t, uint32_t, rc_node_t
*);
675 rc_node_t
*rc_node_setup_snapshot(rc_node_t
*, rc_node_lookup_t
*, const char *,
676 uint32_t, rc_node_t
*);
677 rc_node_t
*rc_node_setup_snaplevel(rc_node_t
*, rc_node_lookup_t
*,
678 rc_snaplevel_t
*, rc_node_t
*);
679 int rc_node_create_property(rc_node_t
*, rc_node_lookup_t
*,
680 const char *, rep_protocol_value_type_t
, const char *, size_t, size_t);
682 rc_node_t
*rc_node_alloc(void);
683 void rc_node_destroy(rc_node_t
*);
686 * rc_node.c, client interface (rc_node_ptr_t, rc_node_iter_t)
688 void rc_node_ptr_init(rc_node_ptr_t
*);
689 int rc_local_scope(uint32_t, rc_node_ptr_t
*);
691 void rc_node_clear(rc_node_ptr_t
*, int);
692 void rc_node_ptr_assign(rc_node_ptr_t
*, const rc_node_ptr_t
*);
693 int rc_node_name(rc_node_ptr_t
*, char *, size_t, uint32_t, size_t *);
694 int rc_node_fmri(rc_node_ptr_t
*, char *, size_t, size_t *);
695 int rc_node_parent_type(rc_node_ptr_t
*, uint32_t *);
696 int rc_node_get_child(rc_node_ptr_t
*, const char *, uint32_t, rc_node_ptr_t
*);
697 int rc_node_get_parent(rc_node_ptr_t
*, uint32_t, rc_node_ptr_t
*);
698 int rc_node_get_property_type(rc_node_ptr_t
*, rep_protocol_value_type_t
*);
699 int rc_node_get_property_value(rc_node_ptr_t
*,
700 struct rep_protocol_value_response
*, size_t *);
701 int rc_node_create_child(rc_node_ptr_t
*, uint32_t, const char *,
703 int rc_node_create_child_pg(rc_node_ptr_t
*, uint32_t, const char *,
704 const char *, uint32_t, rc_node_ptr_t
*);
705 int rc_node_update(rc_node_ptr_t
*);
706 int rc_node_delete(rc_node_ptr_t
*);
707 int rc_node_next_snaplevel(rc_node_ptr_t
*, rc_node_ptr_t
*);
709 int rc_node_setup_iter(rc_node_ptr_t
*, rc_node_iter_t
**, uint32_t,
710 size_t, const char *);
712 int rc_iter_next(rc_node_iter_t
*, rc_node_ptr_t
*, uint32_t);
713 int rc_iter_next_value(rc_node_iter_t
*, struct rep_protocol_value_response
*,
715 void rc_iter_destroy(rc_node_iter_t
**);
717 int rc_node_setup_tx(rc_node_ptr_t
*, rc_node_ptr_t
*);
718 int rc_tx_commit(rc_node_ptr_t
*, const void *, size_t);
720 void rc_pg_notify_init(rc_node_pg_notify_t
*);
721 int rc_pg_notify_setup(rc_node_pg_notify_t
*, rc_node_ptr_t
*, int);
722 void rc_pg_notify_fini(rc_node_pg_notify_t
*);
724 void rc_notify_info_init(rc_notify_info_t
*);
725 int rc_notify_info_add_name(rc_notify_info_t
*, const char *);
726 int rc_notify_info_add_type(rc_notify_info_t
*, const char *);
727 int rc_notify_info_wait(rc_notify_info_t
*, rc_node_ptr_t
*, char *, size_t);
728 void rc_notify_info_fini(rc_notify_info_t
*);
730 int rc_snapshot_take_new(rc_node_ptr_t
*, const char *,
731 const char *, const char *, rc_node_ptr_t
*);
732 int rc_snapshot_take_attach(rc_node_ptr_t
*, rc_node_ptr_t
*);
733 int rc_snapshot_attach(rc_node_ptr_t
*, rc_node_ptr_t
*);
738 int object_fill_children(rc_node_t
*);
739 int object_create(rc_node_t
*, uint32_t, const char *, rc_node_t
**);
740 int object_create_pg(rc_node_t
*, uint32_t, const char *, const char *,
741 uint32_t, rc_node_t
**);
743 int object_delete(rc_node_t
*);
744 void object_free_values(const char *, uint32_t, size_t, size_t);
746 int object_fill_snapshot(rc_snapshot_t
*);
748 int object_snapshot_take_new(rc_node_t
*, const char *, const char *,
749 const char *, rc_node_t
**);
750 int object_snapshot_attach(rc_node_lookup_t
*, uint32_t *, int);
755 int object_tx_commit(rc_node_lookup_t
*, tx_commit_data_t
*, uint32_t *);
757 /* Functions to access transaction commands. */
758 int tx_cmd_action(tx_commit_data_t
*, size_t,
759 enum rep_protocol_transaction_action
*);
760 size_t tx_cmd_count(tx_commit_data_t
*);
761 int tx_cmd_nvalues(tx_commit_data_t
*, size_t, uint32_t *);
762 int tx_cmd_prop(tx_commit_data_t
*, size_t, const char **);
763 int tx_cmd_prop_type(tx_commit_data_t
*, size_t, uint32_t *);
764 int tx_cmd_value(tx_commit_data_t
*, size_t, uint32_t, const char **);
765 void tx_commit_data_free(tx_commit_data_t
*);
766 int tx_commit_data_new(const void *, size_t, tx_commit_data_t
**);
771 int rc_snapshot_get(uint32_t, rc_snapshot_t
**);
772 void rc_snapshot_rele(rc_snapshot_t
*);
773 void rc_snaplevel_hold(rc_snaplevel_t
*);
774 void rc_snaplevel_rele(rc_snaplevel_t
*);
779 int backend_init(const char *, const char *, int);
780 boolean_t
backend_is_upgraded(backend_tx_t
*);
781 void backend_fini(void);
783 rep_protocol_responseid_t
backend_create_backup(const char *);
784 rep_protocol_responseid_t
backend_switch(int);
787 * call on any database inconsistency -- cleans up state as best it can,
788 * and exits with a "Database Bad" error code.
790 void backend_panic(const char *, ...) __NORETURN
;
791 #pragma rarely_called(backend_panic)
793 backend_query_t
*backend_query_alloc(void);
794 void backend_query_append(backend_query_t
*, const char *);
795 void backend_query_add(backend_query_t
*, const char *, ...);
796 void backend_query_free(backend_query_t
*);
798 typedef int backend_run_callback_f(void *data
, int columns
, char **vals
,
800 #define BACKEND_CALLBACK_CONTINUE 0
801 #define BACKEND_CALLBACK_ABORT 1
803 backend_run_callback_f backend_fail_if_seen
; /* aborts TX if called */
805 int backend_run(backend_type_t
, backend_query_t
*,
806 backend_run_callback_f
*, void *);
808 int backend_tx_begin(backend_type_t
, backend_tx_t
**);
809 int backend_tx_begin_ro(backend_type_t
, backend_tx_t
**);
810 void backend_tx_end_ro(backend_tx_t
*);
813 BACKEND_ID_SERVICE_INSTANCE
,
814 BACKEND_ID_PROPERTYGRP
,
815 BACKEND_ID_GENERATION
,
820 BACKEND_ID_SNAPLEVEL
,
821 BACKEND_ID_INVALID
/* always illegal */
824 uint32_t backend_new_id(backend_tx_t
*, enum id_space
);
825 int backend_tx_run_update(backend_tx_t
*, const char *, ...);
826 int backend_tx_run_update_changed(backend_tx_t
*, const char *, ...);
827 int backend_tx_run_single_int(backend_tx_t
*tx
, backend_query_t
*q
,
829 int backend_tx_run(backend_tx_t
*, backend_query_t
*,
830 backend_run_callback_f
*, void *);
832 int backend_tx_commit(backend_tx_t
*);
833 void backend_tx_rollback(backend_tx_t
*);
839 #endif /* _CONFIGD_H */