xref: /illumos-gate/usr/src/cmd/svc/configd/configd.h (revision 3db86aab)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef	_CONFIGD_H
28 #define	_CONFIGD_H
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #include <door.h>
33 #include <pthread.h>
34 #include <string.h>
35 #include <sys/types.h>
36 
37 #include <libscf.h>
38 #include <repcache_protocol.h>
39 #include <libuutil.h>
40 
41 #include <configd_exit.h>
42 
43 #ifdef	__cplusplus
44 extern "C" {
45 #endif
46 
47 /*
48  * Lock order:
49  *
50  *	client lock
51  *		iter locks, in ID order
52  *		entity locks, in ID order
53  *
54  *		(any iter/entity locks)
55  *			backend locks (NORMAL, then NONPERSIST)
56  *				rc_node lock
57  *					children's rc_node lock
58  *				cache bucket lock
59  *					rc_node lock[*]
60  *
61  *	* only one node may be grabbed while holding a bucket lock
62  *
63  *	leaf locks:  (no other locks may be aquired while holding one)
64  *		rc_pg_notify_lock
65  */
66 
67 /*
68  * Returns the minimum size for a structure of type 't' such
69  * that it is safe to access field 'f'.
70  */
71 #define	offsetofend(t, f)	(offsetof(t, f) + sizeof (((t *)0)->f))
72 
73 /*
74  * We want MUTEX_HELD, but we also want pthreads.  So we're stuck with this.
75  */
76 struct _lwp_mutex_t;
77 extern int _mutex_held(struct _lwp_mutex_t *);
78 #define	MUTEX_HELD(m)		_mutex_held((struct _lwp_mutex_t *)(m))
79 
80 /*
81  * Maximum levels of composition.
82  */
83 #define	COMPOSITION_DEPTH	2
84 
85 /*
86  * The default locations of the repository dbs
87  */
88 #define	REPOSITORY_DB	"/etc/svc/repository.db"
89 #define	NONPERSIST_DB	"/etc/svc/volatile/svc_nonpersist.db"
90 
91 #define	CONFIGD_CORE	"core.%f.%t.%p"
92 
93 #ifndef NDEBUG
94 #define	bad_error(f, e)							\
95 	uu_warn("%s:%d: %s() returned bad error %d.  Aborting.\n",	\
96 	    __FILE__, __LINE__, f, e);					\
97 	abort()
98 #else
99 #define	bad_error(f, e)		abort()
100 #endif
101 
102 typedef enum backend_type {
103 	BACKEND_TYPE_NORMAL		= 0,
104 	BACKEND_TYPE_NONPERSIST,
105 	BACKEND_TYPE_TOTAL			/* backend use only */
106 } backend_type_t;
107 
108 /*
109  * pre-declare rc_* types
110  */
111 typedef struct rc_node rc_node_t;
112 typedef struct rc_snapshot rc_snapshot_t;
113 typedef struct rc_snaplevel rc_snaplevel_t;
114 
115 /*
116  * notification layer -- protected by rc_pg_notify_lock
117  */
118 typedef struct rc_notify_info rc_notify_info_t;
119 typedef struct rc_notify_delete rc_notify_delete_t;
120 
121 #define	RC_NOTIFY_MAX_NAMES	4	/* enough for now */
122 
123 typedef struct rc_notify {
124 	uu_list_node_t	rcn_list_node;
125 	rc_node_t	*rcn_node;
126 	rc_notify_info_t *rcn_info;
127 	rc_notify_delete_t *rcn_delete;
128 } rc_notify_t;
129 
130 struct rc_notify_delete {
131 	rc_notify_t rnd_notify;
132 	char rnd_fmri[REP_PROTOCOL_FMRI_LEN];
133 };
134 
135 struct rc_notify_info {
136 	uu_list_node_t	rni_list_node;
137 	rc_notify_t	rni_notify;
138 	const char	*rni_namelist[RC_NOTIFY_MAX_NAMES];
139 	const char	*rni_typelist[RC_NOTIFY_MAX_NAMES];
140 
141 	int		rni_flags;
142 	int		rni_waiters;
143 	pthread_cond_t	rni_cv;
144 };
145 #define	RC_NOTIFY_ACTIVE	0x00000001
146 #define	RC_NOTIFY_DRAIN		0x00000002
147 #define	RC_NOTIFY_EMPTYING	0x00000004
148 
149 typedef struct rc_node_pg_notify {
150 	uu_list_node_t	rnpn_node;
151 	int		rnpn_fd;
152 	rc_node_t	*rnpn_pg;
153 } rc_node_pg_notify_t;
154 
155 /*
156  * cache layer
157  */
158 
159 /*
160  * The 'key' for the main object hash.  main_id is the main object
161  * identifier.  The rl_ids array contains:
162  *
163  *	TYPE		RL_IDS
164  *	scope		unused
165  *	service		unused
166  *	instance	{service_id}
167  *	snapshot	{service_id, instance_id}
168  *	snaplevel	{service_id, instance_id, name_id, snapshot_id}
169  *	propertygroup	{service_id, (instance_id or 0), (name_id or 0),
170  *			    (snapshot_id or 0), (l_id or 0)}
171  *	property	{service_id, (instance_id or 0), (name_id or 0),
172  *			    (snapshot_id or 0), (l_id or 0), pg_id, gen_id}
173  */
174 #define	ID_SERVICE	0
175 #define	ID_INSTANCE	1
176 #define	ID_NAME		2
177 #define	ID_SNAPSHOT	3
178 #define	ID_LEVEL	4
179 #define	ID_PG		5
180 #define	ID_GEN		6
181 #define	MAX_IDS	7
182 typedef struct rc_node_lookup {
183 	uint16_t	rl_type;		/* REP_PROTOCOL_ENTITY_* */
184 	uint16_t	rl_backend;		/* BACKEND_TYPE_* */
185 	uint32_t	rl_main_id;		/* primary identifier */
186 	uint32_t	rl_ids[MAX_IDS];	/* context */
187 } rc_node_lookup_t;
188 
189 struct rc_node {
190 	/*
191 	 * read-only data
192 	 */
193 	rc_node_lookup_t rn_id;			/* must be first */
194 	uint32_t	rn_hash;
195 	const char	*rn_name;
196 
197 	/*
198 	 * type-specific state
199 	 * (if space becomes an issue, these can become a union)
200 	 */
201 
202 	/*
203 	 * Used by instances, snapshots, and "composed property groups" only.
204 	 * These are the entities whose properties should appear composed when
205 	 * this entity is traversed by a composed iterator.  0 is the top-most
206 	 * entity, down to COMPOSITION_DEPTH - 1.
207 	 */
208 	rc_node_t	*rn_cchain[COMPOSITION_DEPTH];
209 
210 	/*
211 	 * used by property groups only
212 	 */
213 	const char	*rn_type;
214 	uint32_t	rn_pgflags;
215 	uint32_t	rn_gen_id;
216 	uu_list_t	*rn_pg_notify_list;	/* prot by rc_pg_notify_lock */
217 	rc_notify_t	rn_notify;		/* prot by rc_pg_notify_lock */
218 
219 	/*
220 	 * used by properties only
221 	 */
222 	rep_protocol_value_type_t rn_valtype;
223 	const char	*rn_values;		/* protected by rn_lock */
224 	size_t		rn_values_count;	/* protected by rn_lock */
225 	size_t		rn_values_size;		/* protected by rn_lock */
226 
227 	/*
228 	 * used by snapshots only
229 	 */
230 	uint32_t	rn_snapshot_id;
231 	rc_snapshot_t	*rn_snapshot;		/* protected by rn_lock */
232 
233 	/*
234 	 * used by snaplevels only
235 	 */
236 	rc_snaplevel_t	*rn_snaplevel;
237 
238 	/*
239 	 * mutable state
240 	 */
241 	pthread_mutex_t	rn_lock;
242 	pthread_cond_t	rn_cv;
243 	uint32_t	rn_flags;
244 	uint32_t	rn_refs;		/* reference count */
245 	uint32_t	rn_other_refs;		/* atomic refcount */
246 	uint32_t	rn_other_refs_held;	/* for 1->0 transitions */
247 
248 	uu_list_t	*rn_children;
249 	uu_list_node_t	rn_sibling_node;
250 
251 	rc_node_t	*rn_parent;		/* set if on child list */
252 	rc_node_t	*rn_former;		/* next former node */
253 	rc_node_t	*rn_parent_ref;		/* reference count target */
254 
255 	/*
256 	 * external state (protected by hash chain lock)
257 	 */
258 	rc_node_t	*rn_hash_next;
259 };
260 
261 /*
262  * flag ordering:
263  *	RC_DYING
264  *		RC_NODE_CHILDREN_CHANGING
265  *		RC_NODE_CREATING_CHILD
266  *		RC_NODE_USING_PARENT
267  *			RC_NODE_IN_TX
268  *
269  * RC_NODE_USING_PARENT is special, because it lets you proceed up the tree,
270  * in the reverse of the usual locking order.  Because of this, there are
271  * limitations on what you can do while holding it.  While holding
272  * RC_NODE_USING_PARENT, you may:
273  *	bump or release your parent's reference count
274  *	access fields in your parent
275  *	hold RC_NODE_USING_PARENT in the parent, proceeding recursively.
276  *
277  * If you are only holding *one* node's RC_NODE_USING_PARENT, and:
278  *	you are *not* proceeding recursively, you can hold your
279  *	    immediate parent's RC_NODE_CHILDREN_CHANGING flag.
280  *	you hold your parent's RC_NODE_CHILDREN_CHANGING flag, you can add
281  *	    RC_NODE_IN_TX to your flags.
282  *	you want to grab a flag in your parent, you must lock your parent,
283  *	    lock yourself, drop RC_NODE_USING_PARENT, unlock yourself,
284  *	    then proceed to manipulate the parent.
285  */
286 #define	RC_NODE_CHILDREN_CHANGING	0x00000001 /* child list in flux */
287 #define	RC_NODE_HAS_CHILDREN		0x00000002 /* child list is accurate */
288 
289 #define	RC_NODE_IN_PARENT		0x00000004 /* I'm in my parent's list */
290 #define	RC_NODE_USING_PARENT		0x00000008 /* parent ptr in use */
291 #define	RC_NODE_CREATING_CHILD		0x00000010 /* a create is in progress */
292 #define	RC_NODE_IN_TX			0x00000020 /* a tx is in progess */
293 
294 #define	RC_NODE_OLD			0x00000400 /* out-of-date object */
295 #define	RC_NODE_ON_FORMER		0x00000800 /* on an rn_former list */
296 
297 #define	RC_NODE_PARENT_REF		0x00001000 /* parent_ref in use */
298 #define	RC_NODE_UNREFED			0x00002000 /* unref processing active */
299 #define	RC_NODE_DYING			0x00004000 /* node is being deleted */
300 #define	RC_NODE_DEAD			0x00008000 /* node has been deleted */
301 
302 #define	RC_NODE_DYING_FLAGS						\
303 	(RC_NODE_CHILDREN_CHANGING | RC_NODE_IN_TX | RC_NODE_DYING |	\
304 	    RC_NODE_CREATING_CHILD)
305 
306 #define	RC_NODE_WAITING_FLAGS						\
307 	(RC_NODE_DYING_FLAGS | RC_NODE_USING_PARENT)
308 
309 
310 typedef struct rc_node_ptr {
311 	rc_node_t	*rnp_node;
312 	char		rnp_authorized;		/* transaction pre-authed */
313 	char		rnp_deleted;		/* object was deleted */
314 } rc_node_ptr_t;
315 
316 #define	NODE_PTR_NOT_HELD(npp) \
317 	    ((npp)->rnp_node == NULL || !MUTEX_HELD(&(npp)->rnp_node->rn_lock))
318 
319 typedef int rc_iter_filter_func(rc_node_t *, void *);
320 
321 typedef struct rc_node_iter {
322 	rc_node_t	*rni_parent;
323 	int		rni_clevel;	/* index into rni_parent->rn_cchain[] */
324 	rc_node_t	*rni_iter_node;
325 	uu_list_walk_t	*rni_iter;
326 	uint32_t	rni_type;
327 
328 	/*
329 	 * for normal walks
330 	 */
331 	rc_iter_filter_func *rni_filter;
332 	void		*rni_filter_arg;
333 
334 	/*
335 	 * for value walks
336 	 */
337 	uint32_t	rni_offset;		/* next value offset */
338 	uint32_t	rni_last_offset;	/* previous value offset */
339 } rc_node_iter_t;
340 
341 typedef struct rc_node_tx {
342 	rc_node_ptr_t	rnt_ptr;
343 	int		rnt_authorized;		/* No need to check anymore. */
344 } rc_node_tx_t;
345 
346 
347 typedef struct cache_bucket {
348 	pthread_mutex_t	cb_lock;
349 	rc_node_t	*cb_head;
350 
351 	char		cb_pad[64 - sizeof (pthread_mutex_t) -
352 			    2 * sizeof (rc_node_t *)];
353 } cache_bucket_t;
354 
355 /*
356  * Snapshots
357  */
358 struct rc_snapshot {
359 	uint32_t	rs_snap_id;
360 
361 	pthread_mutex_t	rs_lock;
362 	pthread_cond_t	rs_cv;
363 
364 	uint32_t	rs_flags;
365 	uint32_t	rs_refcnt;	/* references from rc_nodes */
366 	uint32_t	rs_childref;	/* references to children */
367 
368 	rc_snaplevel_t	*rs_levels;	/* list of levels */
369 	rc_snapshot_t	*rs_hash_next;
370 };
371 #define	RC_SNAPSHOT_FILLING	0x00000001	/* rs_levels changing */
372 #define	RC_SNAPSHOT_READY	0x00000002
373 #define	RC_SNAPSHOT_DEAD	0x00000004	/* no resources */
374 
375 typedef struct rc_snaplevel_pgs {
376 	uint32_t	rsp_pg_id;
377 	uint32_t	rsp_gen_id;
378 } rc_snaplevel_pgs_t;
379 
380 struct rc_snaplevel {
381 	rc_snapshot_t	*rsl_parent;
382 	uint32_t	rsl_level_num;
383 	uint32_t	rsl_level_id;
384 
385 	uint32_t	rsl_service_id;
386 	uint32_t	rsl_instance_id;
387 
388 	const char	*rsl_scope;
389 	const char	*rsl_service;
390 	const char	*rsl_instance;
391 
392 	rc_snaplevel_t	*rsl_next;
393 };
394 
395 /*
396  * Client layer -- the IDs fields must be first, in order for the search
397  * routines to work correctly.
398  */
399 enum repcache_txstate {
400 	REPCACHE_TX_INIT,
401 	REPCACHE_TX_SETUP,
402 	REPCACHE_TX_COMMITTED
403 };
404 
405 typedef struct repcache_entity {
406 	uint32_t	re_id;
407 	uu_avl_node_t	re_link;
408 	uint32_t	re_changeid;
409 
410 	pthread_mutex_t	re_lock;
411 	uint32_t	re_type;
412 	rc_node_ptr_t	re_node;
413 	enum repcache_txstate re_txstate;	/* property groups only */
414 } repcache_entity_t;
415 
416 typedef struct repcache_iter {
417 	uint32_t	ri_id;
418 	uu_avl_node_t	ri_link;
419 
420 	uint32_t	ri_type;	/* result type */
421 
422 	pthread_mutex_t	ri_lock;
423 	uint32_t	ri_sequence;
424 	rc_node_iter_t	*ri_iter;
425 } repcache_iter_t;
426 
427 typedef struct repcache_client {
428 	/*
429 	 * constants
430 	 */
431 	uint32_t	rc_id;		/* must be first */
432 	int		rc_all_auths;	/* bypass auth checks */
433 	uint32_t	rc_debug;	/* debug flags */
434 	pid_t		rc_pid;		/* pid of opening process */
435 	door_id_t	rc_doorid;	/* a globally unique identifier */
436 	int		rc_doorfd;	/* our door's FD */
437 
438 	/*
439 	 * client list linkage, protected by hash chain lock
440 	 */
441 	uu_list_node_t	rc_link;
442 
443 	/*
444 	 * notification information, protected by rc_node layer
445 	 */
446 	rc_node_pg_notify_t	rc_pg_notify;
447 	rc_notify_info_t	rc_notify_info;
448 
449 	/*
450 	 * client_wait output, only usable by rc_notify_thr
451 	 */
452 	rc_node_ptr_t	rc_notify_ptr;
453 
454 	/*
455 	 * register sets, protected by rc_lock
456 	 */
457 	uu_avl_t	*rc_entities;
458 	uu_avl_t	*rc_iters;
459 
460 	/*
461 	 * Variables, protected by rc_lock
462 	 */
463 	int		rc_refcnt;	/* in-progress door calls */
464 	int		rc_flags;	/* state */
465 	uint32_t	rc_changeid;	/* used to make backups idempotent */
466 	pthread_t	rc_insert_thr;	/* single thread trying to insert */
467 	pthread_t	rc_notify_thr;	/* single thread waiting for notify */
468 	pthread_cond_t	rc_cv;
469 	pthread_mutex_t	rc_lock;
470 } repcache_client_t;
471 #define	RC_CLIENT_DEAD			0x00000001
472 
473 typedef struct client_bucket {
474 	pthread_mutex_t	cb_lock;
475 	uu_list_t	*cb_list;
476 	char ch_pad[64 - sizeof (pthread_mutex_t) - sizeof (uu_list_t *)];
477 } client_bucket_t;
478 
479 enum rc_ptr_type {
480 	RC_PTR_TYPE_ENTITY = 1,
481 	RC_PTR_TYPE_ITER
482 };
483 
484 typedef struct request_log_ptr {
485 	enum rc_ptr_type	rlp_type;
486 	uint32_t		rlp_id;
487 	void			*rlp_ptr; /* repcache_{entity,iter}_t */
488 	void			*rlp_data;	/* rc_node, for ENTITY only */
489 } request_log_ptr_t;
490 
491 #define	MAX_PTRS	3
492 
493 /*
494  * rl_start through rl_client cannot move without changing start_log()
495  */
496 typedef struct request_log_entry {
497 	hrtime_t		rl_start;
498 	hrtime_t		rl_end;
499 	pthread_t		rl_tid;
500 	uint32_t		rl_clientid;
501 	repcache_client_t	*rl_client;
502 	enum rep_protocol_requestid rl_request;
503 	rep_protocol_responseid_t rl_response;
504 	int			rl_num_ptrs;
505 	request_log_ptr_t	rl_ptrs[MAX_PTRS];
506 } request_log_entry_t;
507 
508 /*
509  * thread information
510  */
511 typedef enum thread_state {
512 	TI_CREATED,
513 	TI_DOOR_RETURN,
514 	TI_SIGNAL_WAIT,
515 	TI_MAIN_DOOR_CALL,
516 	TI_CLIENT_CALL
517 } thread_state_t;
518 
519 typedef struct thread_info {
520 	pthread_t	ti_thread;
521 	uu_list_node_t	ti_node;		/* for list of all thread */
522 
523 	/*
524 	 * per-thread globals
525 	 */
526 	ucred_t		*ti_ucred;		/* for credential lookups */
527 	int		ti_ucred_read;		/* ucred holds current creds */
528 
529 	/*
530 	 * per-thread state information, for debuggers
531 	 */
532 	hrtime_t	ti_lastchange;
533 
534 	thread_state_t	ti_state;
535 	thread_state_t	ti_prev_state;
536 
537 	repcache_client_t *ti_active_client;
538 	request_log_entry_t	ti_log;
539 
540 	struct rep_protocol_request *ti_client_request;
541 	repository_door_request_t *ti_main_door_request;
542 
543 } thread_info_t;
544 
545 /*
546  * Backend layer
547  */
548 typedef struct backend_query backend_query_t;
549 typedef struct backend_tx backend_tx_t;
550 
551 /*
552  * configd.c
553  */
554 int create_connection(ucred_t *cred, repository_door_request_t *rp,
555     size_t rp_size, int *out_fd);
556 
557 thread_info_t *thread_self(void);
558 void thread_newstate(thread_info_t *, thread_state_t);
559 ucred_t *get_ucred(void);
560 int ucred_is_privileged(ucred_t *);
561 
562 void configd_critical(const char *, ...);
563 void configd_vcritical(const char *, va_list);
564 
565 extern int is_main_repository;
566 extern int max_repository_backups;
567 
568 /*
569  * maindoor.c
570  */
571 int setup_main_door(const char *);
572 
573 /*
574  * client.c
575  */
576 int create_client(pid_t, uint32_t, int, int *);
577 int client_init(void);
578 int client_is_privileged(void);
579 void log_enter(request_log_entry_t *);
580 
581 /*
582  * rc_node.c, backend/cache interfaces (rc_node_t)
583  */
584 int rc_node_init();
585 int rc_check_type_name(uint32_t, const char *);
586 
587 void rc_node_rele(rc_node_t *);
588 rc_node_t *rc_node_setup(rc_node_t *, rc_node_lookup_t *,
589     const char *, rc_node_t *);
590 rc_node_t *rc_node_setup_pg(rc_node_t *, rc_node_lookup_t *, const char *,
591     const char *, uint32_t, uint32_t, rc_node_t *);
592 rc_node_t *rc_node_setup_snapshot(rc_node_t *, rc_node_lookup_t *, const char *,
593     uint32_t, rc_node_t *);
594 rc_node_t *rc_node_setup_snaplevel(rc_node_t *, rc_node_lookup_t *,
595     rc_snaplevel_t *, rc_node_t *);
596 int rc_node_create_property(rc_node_t *, rc_node_lookup_t *,
597     const char *, rep_protocol_value_type_t, const char *, size_t, size_t);
598 
599 rc_node_t *rc_node_alloc(void);
600 void rc_node_destroy(rc_node_t *);
601 
602 /*
603  * rc_node.c, client interface (rc_node_ptr_t, rc_node_iter_t)
604  */
605 void rc_node_ptr_init(rc_node_ptr_t *);
606 int rc_local_scope(uint32_t, rc_node_ptr_t *);
607 
608 void rc_node_clear(rc_node_ptr_t *, int);
609 void rc_node_ptr_assign(rc_node_ptr_t *, const rc_node_ptr_t *);
610 int rc_node_name(rc_node_ptr_t *, char *, size_t, uint32_t, size_t *);
611 int rc_node_fmri(rc_node_ptr_t *, char *, size_t, size_t *);
612 int rc_node_parent_type(rc_node_ptr_t *, uint32_t *);
613 int rc_node_get_child(rc_node_ptr_t *, const char *, uint32_t, rc_node_ptr_t *);
614 int rc_node_get_parent(rc_node_ptr_t *, uint32_t, rc_node_ptr_t *);
615 int rc_node_get_property_type(rc_node_ptr_t *, rep_protocol_value_type_t *);
616 int rc_node_get_property_value(rc_node_ptr_t *,
617     struct rep_protocol_value_response *, size_t *);
618 int rc_node_create_child(rc_node_ptr_t *, uint32_t, const char *,
619     rc_node_ptr_t *);
620 int rc_node_create_child_pg(rc_node_ptr_t *, uint32_t, const char *,
621     const char *, uint32_t, rc_node_ptr_t *);
622 int rc_node_update(rc_node_ptr_t *);
623 int rc_node_delete(rc_node_ptr_t *);
624 int rc_node_next_snaplevel(rc_node_ptr_t *, rc_node_ptr_t *);
625 
626 int rc_node_setup_iter(rc_node_ptr_t *, rc_node_iter_t **, uint32_t,
627     size_t, const char *);
628 
629 int rc_iter_next(rc_node_iter_t *, rc_node_ptr_t *, uint32_t);
630 int rc_iter_next_value(rc_node_iter_t *, struct rep_protocol_value_response *,
631     size_t *, int);
632 void rc_iter_destroy(rc_node_iter_t **);
633 
634 int rc_node_setup_tx(rc_node_ptr_t *, rc_node_ptr_t *);
635 int rc_tx_commit(rc_node_ptr_t *, const void *, size_t);
636 
637 void rc_pg_notify_init(rc_node_pg_notify_t *);
638 int rc_pg_notify_setup(rc_node_pg_notify_t *, rc_node_ptr_t *, int);
639 void rc_pg_notify_fini(rc_node_pg_notify_t *);
640 
641 void rc_notify_info_init(rc_notify_info_t *);
642 int rc_notify_info_add_name(rc_notify_info_t *, const char *);
643 int rc_notify_info_add_type(rc_notify_info_t *, const char *);
644 int rc_notify_info_wait(rc_notify_info_t *, rc_node_ptr_t *, char *, size_t);
645 void rc_notify_info_fini(rc_notify_info_t *);
646 
647 int rc_snapshot_take_new(rc_node_ptr_t *, const char *,
648     const char *, const char *, rc_node_ptr_t *);
649 int rc_snapshot_take_attach(rc_node_ptr_t *, rc_node_ptr_t *);
650 int rc_snapshot_attach(rc_node_ptr_t *, rc_node_ptr_t *);
651 
652 /*
653  * file_object.c
654  */
655 int object_fill_children(rc_node_t *);
656 int object_create(rc_node_t *, uint32_t, const char *, rc_node_t **);
657 int object_create_pg(rc_node_t *, uint32_t, const char *, const char *,
658     uint32_t, rc_node_t **);
659 
660 int object_delete(rc_node_t *);
661 void object_free_values(const char *, uint32_t, size_t, size_t);
662 
663 int object_fill_snapshot(rc_snapshot_t *);
664 
665 int object_snapshot_take_new(rc_node_t *, const char *, const char *,
666     const char *, rc_node_t **);
667 int object_snapshot_attach(rc_node_lookup_t *, uint32_t *, int);
668 
669 /*
670  * object.c
671  */
672 int object_tx_commit(rc_node_lookup_t *, const void *, size_t, uint32_t *);
673 
674 /*
675  * snapshot.c
676  */
677 int rc_snapshot_get(uint32_t, rc_snapshot_t **);
678 void rc_snapshot_rele(rc_snapshot_t *);
679 void rc_snaplevel_hold(rc_snaplevel_t *);
680 void rc_snaplevel_rele(rc_snaplevel_t *);
681 
682 /*
683  * backend.c
684  */
685 int backend_init(const char *, const char *, int);
686 void backend_fini(void);
687 
688 rep_protocol_responseid_t backend_create_backup(const char *);
689 
690 /*
691  * call on any database inconsistency -- cleans up state as best it can,
692  * and exits with a "Database Bad" error code.
693  */
694 void backend_panic(const char *, ...) __NORETURN;
695 #pragma rarely_called(backend_panic)
696 
697 backend_query_t *backend_query_alloc(void);
698 void backend_query_append(backend_query_t *, const char *);
699 void backend_query_add(backend_query_t *, const char *, ...);
700 void backend_query_free(backend_query_t *);
701 
702 typedef int backend_run_callback_f(void *data, int columns, char **vals,
703     char **names);
704 #define	BACKEND_CALLBACK_CONTINUE	0
705 #define	BACKEND_CALLBACK_ABORT		1
706 
707 backend_run_callback_f backend_fail_if_seen;	/* aborts TX if called */
708 
709 int backend_run(backend_type_t, backend_query_t *,
710     backend_run_callback_f *, void *);
711 
712 int backend_tx_begin(backend_type_t, backend_tx_t **);
713 int backend_tx_begin_ro(backend_type_t, backend_tx_t **);
714 void backend_tx_end_ro(backend_tx_t *);
715 
716 enum id_space {
717 	BACKEND_ID_SERVICE_INSTANCE,
718 	BACKEND_ID_PROPERTYGRP,
719 	BACKEND_ID_GENERATION,
720 	BACKEND_ID_PROPERTY,
721 	BACKEND_ID_VALUE,
722 	BACKEND_ID_SNAPNAME,
723 	BACKEND_ID_SNAPSHOT,
724 	BACKEND_ID_SNAPLEVEL,
725 	BACKEND_ID_INVALID	/* always illegal */
726 };
727 
728 uint32_t backend_new_id(backend_tx_t *, enum id_space);
729 int backend_tx_run_update(backend_tx_t *, const char *, ...);
730 int backend_tx_run_update_changed(backend_tx_t *, const char *, ...);
731 int backend_tx_run_single_int(backend_tx_t *tx, backend_query_t *q,
732     uint32_t *buf);
733 int backend_tx_run(backend_tx_t *, backend_query_t *,
734     backend_run_callback_f *, void *);
735 
736 int backend_tx_commit(backend_tx_t *);
737 void backend_tx_rollback(backend_tx_t *);
738 
739 #ifdef	__cplusplus
740 }
741 #endif
742 
743 #endif	/* _CONFIGD_H */
744