xref: /titanic_50/usr/src/cmd/svc/configd/file_object.c (revision 6e1d2b428379e5270ccda99d403eb225e8699c3e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*6e1d2b42Samaguire  * Common Development and Distribution License (the "License").
6*6e1d2b42Samaguire  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*6e1d2b42Samaguire  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * file_object.c - enter objects into and load them from the backend
307c478bd9Sstevel@tonic-gate  *
317c478bd9Sstevel@tonic-gate  * The primary entry points in this layer are object_create(),
327c478bd9Sstevel@tonic-gate  * object_create_pg(), object_delete(), and object_fill_children().  They each
337c478bd9Sstevel@tonic-gate  * take an rc_node_t and use the functions in the object_info_t info array for
347c478bd9Sstevel@tonic-gate  * the node's type.
357c478bd9Sstevel@tonic-gate  */
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include <assert.h>
387c478bd9Sstevel@tonic-gate #include <pthread.h>
397c478bd9Sstevel@tonic-gate #include <stdio.h>
407c478bd9Sstevel@tonic-gate #include <stdlib.h>
417c478bd9Sstevel@tonic-gate #include <string.h>
427c478bd9Sstevel@tonic-gate #include <strings.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #include "configd.h"
457c478bd9Sstevel@tonic-gate #include "repcache_protocol.h"
467c478bd9Sstevel@tonic-gate 
477c478bd9Sstevel@tonic-gate typedef struct child_info {
487c478bd9Sstevel@tonic-gate 	rc_node_t	*ci_parent;
497c478bd9Sstevel@tonic-gate 	backend_tx_t	*ci_tx;			/* only for properties */
507c478bd9Sstevel@tonic-gate 	rc_node_lookup_t ci_base_nl;
517c478bd9Sstevel@tonic-gate } child_info_t;
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate typedef struct delete_ent delete_ent_t;
547c478bd9Sstevel@tonic-gate typedef struct delete_stack delete_stack_t;
557c478bd9Sstevel@tonic-gate typedef struct delete_info delete_info_t;
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate typedef int	delete_cb_func(delete_info_t *, const delete_ent_t *);
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate struct delete_ent {
607c478bd9Sstevel@tonic-gate 	delete_cb_func	*de_cb;		/* callback */
617c478bd9Sstevel@tonic-gate 	uint32_t	de_backend;
627c478bd9Sstevel@tonic-gate 	uint32_t	de_id;
637c478bd9Sstevel@tonic-gate 	uint32_t	de_gen;		/* only for property groups */
647c478bd9Sstevel@tonic-gate };
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate struct delete_stack {
677c478bd9Sstevel@tonic-gate 	struct delete_stack *ds_next;
687c478bd9Sstevel@tonic-gate 	uint32_t	ds_size;	/* number of elements */
697c478bd9Sstevel@tonic-gate 	uint32_t	ds_cur;		/* current offset */
707c478bd9Sstevel@tonic-gate 	delete_ent_t	ds_buf[1];	/* actually ds_size */
717c478bd9Sstevel@tonic-gate };
727c478bd9Sstevel@tonic-gate #define	DELETE_STACK_SIZE(x)	offsetof(delete_stack_t, ds_buf[(x)])
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate struct delete_info {
757c478bd9Sstevel@tonic-gate 	backend_tx_t	*di_tx;
767c478bd9Sstevel@tonic-gate 	backend_tx_t	*di_np_tx;
777c478bd9Sstevel@tonic-gate 	delete_stack_t	*di_stack;
787c478bd9Sstevel@tonic-gate 	delete_stack_t	*di_free;
797c478bd9Sstevel@tonic-gate };
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate typedef struct object_info {
827c478bd9Sstevel@tonic-gate 	uint32_t	obj_type;
837c478bd9Sstevel@tonic-gate 	enum id_space	obj_id_space;
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 	int (*obj_fill_children)(rc_node_t *);
867c478bd9Sstevel@tonic-gate 	int (*obj_setup_child_info)(rc_node_t *, uint32_t, child_info_t *);
877c478bd9Sstevel@tonic-gate 	int (*obj_query_child)(backend_query_t *, rc_node_lookup_t *,
887c478bd9Sstevel@tonic-gate 	    const char *);
897c478bd9Sstevel@tonic-gate 	int (*obj_insert_child)(backend_tx_t *, rc_node_lookup_t *,
907c478bd9Sstevel@tonic-gate 	    const char *);
917c478bd9Sstevel@tonic-gate 	int (*obj_insert_pg_child)(backend_tx_t *, rc_node_lookup_t *,
927c478bd9Sstevel@tonic-gate 	    const char *, const char *, uint32_t, uint32_t);
937c478bd9Sstevel@tonic-gate 	int (*obj_delete_start)(rc_node_t *, delete_info_t *);
947c478bd9Sstevel@tonic-gate } object_info_t;
957c478bd9Sstevel@tonic-gate 
968918dff3Sjwadams static void
string_to_id(const char * str,uint32_t * output,const char * fieldname)978918dff3Sjwadams string_to_id(const char *str, uint32_t *output, const char *fieldname)
988918dff3Sjwadams {
998918dff3Sjwadams 	if (uu_strtouint(str, output, sizeof (*output), 0, 0, 0) == -1)
1008918dff3Sjwadams 		backend_panic("invalid integer \"%s\" in field \"%s\"",
1018918dff3Sjwadams 		    str, fieldname);
1028918dff3Sjwadams }
1038918dff3Sjwadams 
1047c478bd9Sstevel@tonic-gate #define	NUM_NEEDED	50
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate static int
delete_stack_push(delete_info_t * dip,uint32_t be,delete_cb_func * cb,uint32_t id,uint32_t gen)1077c478bd9Sstevel@tonic-gate delete_stack_push(delete_info_t *dip, uint32_t be, delete_cb_func *cb,
1087c478bd9Sstevel@tonic-gate     uint32_t id, uint32_t gen)
1097c478bd9Sstevel@tonic-gate {
1107c478bd9Sstevel@tonic-gate 	delete_stack_t *cur = dip->di_stack;
1117c478bd9Sstevel@tonic-gate 	delete_ent_t *ent;
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	if (cur == NULL || cur->ds_cur == cur->ds_size) {
1147c478bd9Sstevel@tonic-gate 		delete_stack_t *new = dip->di_free;
1157c478bd9Sstevel@tonic-gate 		dip->di_free = NULL;
1167c478bd9Sstevel@tonic-gate 		if (new == NULL) {
1177c478bd9Sstevel@tonic-gate 			new = uu_zalloc(DELETE_STACK_SIZE(NUM_NEEDED));
1187c478bd9Sstevel@tonic-gate 			if (new == NULL)
1197c478bd9Sstevel@tonic-gate 				return (REP_PROTOCOL_FAIL_NO_RESOURCES);
1207c478bd9Sstevel@tonic-gate 			new->ds_size = NUM_NEEDED;
1217c478bd9Sstevel@tonic-gate 		}
1227c478bd9Sstevel@tonic-gate 		new->ds_cur = 0;
1237c478bd9Sstevel@tonic-gate 		new->ds_next = dip->di_stack;
1247c478bd9Sstevel@tonic-gate 		dip->di_stack = new;
1257c478bd9Sstevel@tonic-gate 		cur = new;
1267c478bd9Sstevel@tonic-gate 	}
1277c478bd9Sstevel@tonic-gate 	assert(cur->ds_cur < cur->ds_size);
1287c478bd9Sstevel@tonic-gate 	ent = &cur->ds_buf[cur->ds_cur++];
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	ent->de_backend = be;
1317c478bd9Sstevel@tonic-gate 	ent->de_cb = cb;
1327c478bd9Sstevel@tonic-gate 	ent->de_id = id;
1337c478bd9Sstevel@tonic-gate 	ent->de_gen = gen;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	return (REP_PROTOCOL_SUCCESS);
1367c478bd9Sstevel@tonic-gate }
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate static int
delete_stack_pop(delete_info_t * dip,delete_ent_t * out)1397c478bd9Sstevel@tonic-gate delete_stack_pop(delete_info_t *dip, delete_ent_t *out)
1407c478bd9Sstevel@tonic-gate {
1417c478bd9Sstevel@tonic-gate 	delete_stack_t *cur = dip->di_stack;
1427c478bd9Sstevel@tonic-gate 	delete_ent_t *ent;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	if (cur == NULL)
1450b5c9250Shg115875 		return (0);
1467c478bd9Sstevel@tonic-gate 	assert(cur->ds_cur > 0 && cur->ds_cur <= cur->ds_size);
1477c478bd9Sstevel@tonic-gate 	ent = &cur->ds_buf[--cur->ds_cur];
1487c478bd9Sstevel@tonic-gate 	if (cur->ds_cur == 0) {
1497c478bd9Sstevel@tonic-gate 		dip->di_stack = cur->ds_next;
1507c478bd9Sstevel@tonic-gate 		cur->ds_next = NULL;
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 		if (dip->di_free != NULL)
1537c478bd9Sstevel@tonic-gate 			uu_free(dip->di_free);
1547c478bd9Sstevel@tonic-gate 		dip->di_free = cur;
1557c478bd9Sstevel@tonic-gate 	}
1567c478bd9Sstevel@tonic-gate 	if (ent == NULL)
1577c478bd9Sstevel@tonic-gate 		return (0);
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	*out = *ent;
1607c478bd9Sstevel@tonic-gate 	return (1);
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate static void
delete_stack_cleanup(delete_info_t * dip)1647c478bd9Sstevel@tonic-gate delete_stack_cleanup(delete_info_t *dip)
1657c478bd9Sstevel@tonic-gate {
1667c478bd9Sstevel@tonic-gate 	delete_stack_t *cur;
1677c478bd9Sstevel@tonic-gate 	while ((cur = dip->di_stack) != NULL) {
1687c478bd9Sstevel@tonic-gate 		dip->di_stack = cur->ds_next;
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 		uu_free(cur);
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 	if ((cur = dip->di_free) != NULL) {
1747c478bd9Sstevel@tonic-gate 		assert(cur->ds_next == NULL);	/* should only be one */
1757c478bd9Sstevel@tonic-gate 		uu_free(cur);
1767c478bd9Sstevel@tonic-gate 		dip->di_free = NULL;
1777c478bd9Sstevel@tonic-gate 	}
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate struct delete_cb_info {
1817c478bd9Sstevel@tonic-gate 	delete_info_t	*dci_dip;
1827c478bd9Sstevel@tonic-gate 	uint32_t	dci_be;
1837c478bd9Sstevel@tonic-gate 	delete_cb_func	*dci_cb;
1847c478bd9Sstevel@tonic-gate 	int		dci_result;
1857c478bd9Sstevel@tonic-gate };
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1887c478bd9Sstevel@tonic-gate static int
push_delete_callback(void * data,int columns,char ** vals,char ** names)1897c478bd9Sstevel@tonic-gate push_delete_callback(void *data, int columns, char **vals, char **names)
1907c478bd9Sstevel@tonic-gate {
1917c478bd9Sstevel@tonic-gate 	struct delete_cb_info *info = data;
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 	const char *id_str = *vals++;
1947c478bd9Sstevel@tonic-gate 	const char *gen_str = *vals++;
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	uint32_t id;
1977c478bd9Sstevel@tonic-gate 	uint32_t gen;
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	assert(columns == 2);
2007c478bd9Sstevel@tonic-gate 
2018918dff3Sjwadams 	string_to_id(id_str, &id, "id");
2028918dff3Sjwadams 	string_to_id(gen_str, &gen, "gen_id");
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	info->dci_result = delete_stack_push(info->dci_dip, info->dci_be,
2057c478bd9Sstevel@tonic-gate 	    info->dci_cb, id, gen);
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	if (info->dci_result != REP_PROTOCOL_SUCCESS)
2087c478bd9Sstevel@tonic-gate 		return (BACKEND_CALLBACK_ABORT);
2097c478bd9Sstevel@tonic-gate 	return (BACKEND_CALLBACK_CONTINUE);
2107c478bd9Sstevel@tonic-gate }
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate static int
value_delete(delete_info_t * dip,const delete_ent_t * ent)2137c478bd9Sstevel@tonic-gate value_delete(delete_info_t *dip, const delete_ent_t *ent)
2147c478bd9Sstevel@tonic-gate {
2157c478bd9Sstevel@tonic-gate 	uint32_t be = ent->de_backend;
2167c478bd9Sstevel@tonic-gate 	int r;
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	backend_query_t *q;
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 	backend_tx_t *tx = (be == BACKEND_TYPE_NORMAL)? dip->di_tx :
2217c478bd9Sstevel@tonic-gate 	    dip->di_np_tx;
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 	backend_query_add(q,
2267c478bd9Sstevel@tonic-gate 	    "SELECT 1 FROM prop_lnk_tbl WHERE (lnk_val_id = %d); "
2277c478bd9Sstevel@tonic-gate 	    "DELETE FROM value_tbl WHERE (value_id = %d); ",
2287c478bd9Sstevel@tonic-gate 	    ent->de_id, ent->de_id);
2297c478bd9Sstevel@tonic-gate 	r = backend_tx_run(tx, q, backend_fail_if_seen, NULL);
2307c478bd9Sstevel@tonic-gate 	backend_query_free(q);
2317c478bd9Sstevel@tonic-gate 	if (r == REP_PROTOCOL_DONE)
2327c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUCCESS);		/* still in use */
2337c478bd9Sstevel@tonic-gate 	return (r);
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate static int
pg_lnk_tbl_delete(delete_info_t * dip,const delete_ent_t * ent)2377c478bd9Sstevel@tonic-gate pg_lnk_tbl_delete(delete_info_t *dip, const delete_ent_t *ent)
2387c478bd9Sstevel@tonic-gate {
2397c478bd9Sstevel@tonic-gate 	struct delete_cb_info info;
2407c478bd9Sstevel@tonic-gate 	uint32_t be = ent->de_backend;
2417c478bd9Sstevel@tonic-gate 	int r;
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 	backend_query_t *q;
2447c478bd9Sstevel@tonic-gate 
2457c478bd9Sstevel@tonic-gate 	backend_tx_t *tx = (be == BACKEND_TYPE_NORMAL)? dip->di_tx :
2467c478bd9Sstevel@tonic-gate 	    dip->di_np_tx;
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	/*
2497c478bd9Sstevel@tonic-gate 	 * For non-persistent backends, we could only have one parent, and
2507c478bd9Sstevel@tonic-gate 	 * he's already been deleted.
2517c478bd9Sstevel@tonic-gate 	 *
2527c478bd9Sstevel@tonic-gate 	 * For normal backends, we need to check to see if we're in
2537c478bd9Sstevel@tonic-gate 	 * a snapshot or are the active generation for the property
2547c478bd9Sstevel@tonic-gate 	 * group.  If we are, there's nothing to be done.
2557c478bd9Sstevel@tonic-gate 	 */
2567c478bd9Sstevel@tonic-gate 	if (be == BACKEND_TYPE_NORMAL) {
2577c478bd9Sstevel@tonic-gate 		q = backend_query_alloc();
2587c478bd9Sstevel@tonic-gate 		backend_query_add(q,
2597c478bd9Sstevel@tonic-gate 		    "SELECT 1 "
2607c478bd9Sstevel@tonic-gate 		    "FROM pg_tbl "
2617c478bd9Sstevel@tonic-gate 		    "WHERE (pg_id = %d AND pg_gen_id = %d); "
2627c478bd9Sstevel@tonic-gate 		    "SELECT 1 "
2637c478bd9Sstevel@tonic-gate 		    "FROM snaplevel_lnk_tbl "
2647c478bd9Sstevel@tonic-gate 		    "WHERE (snaplvl_pg_id = %d AND snaplvl_gen_id = %d);",
2657c478bd9Sstevel@tonic-gate 		    ent->de_id, ent->de_gen,
2667c478bd9Sstevel@tonic-gate 		    ent->de_id, ent->de_gen);
2677c478bd9Sstevel@tonic-gate 		r = backend_tx_run(tx, q, backend_fail_if_seen, NULL);
2687c478bd9Sstevel@tonic-gate 		backend_query_free(q);
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 		if (r == REP_PROTOCOL_DONE)
2717c478bd9Sstevel@tonic-gate 			return (REP_PROTOCOL_SUCCESS);	/* still in use */
2727c478bd9Sstevel@tonic-gate 	}
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	info.dci_dip = dip;
2757c478bd9Sstevel@tonic-gate 	info.dci_be =  be;
2767c478bd9Sstevel@tonic-gate 	info.dci_cb = &value_delete;
2777c478bd9Sstevel@tonic-gate 	info.dci_result = REP_PROTOCOL_SUCCESS;
2787c478bd9Sstevel@tonic-gate 
2797c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
2807c478bd9Sstevel@tonic-gate 	backend_query_add(q,
2817c478bd9Sstevel@tonic-gate 	    "SELECT DISTINCT lnk_val_id, 0 FROM prop_lnk_tbl "
2827c478bd9Sstevel@tonic-gate 	    "WHERE "
2837c478bd9Sstevel@tonic-gate 	    "    (lnk_pg_id = %d AND lnk_gen_id = %d AND lnk_val_id NOTNULL); "
2847c478bd9Sstevel@tonic-gate 	    "DELETE FROM prop_lnk_tbl "
2857c478bd9Sstevel@tonic-gate 	    "WHERE (lnk_pg_id = %d AND lnk_gen_id = %d)",
2867c478bd9Sstevel@tonic-gate 	    ent->de_id, ent->de_gen, ent->de_id, ent->de_gen);
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	r = backend_tx_run(tx, q, push_delete_callback, &info);
2897c478bd9Sstevel@tonic-gate 	backend_query_free(q);
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate 	if (r == REP_PROTOCOL_DONE) {
2927c478bd9Sstevel@tonic-gate 		assert(info.dci_result != REP_PROTOCOL_SUCCESS);
2937c478bd9Sstevel@tonic-gate 		return (info.dci_result);
2947c478bd9Sstevel@tonic-gate 	}
2957c478bd9Sstevel@tonic-gate 	return (r);
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate static int
propertygrp_delete(delete_info_t * dip,const delete_ent_t * ent)2997c478bd9Sstevel@tonic-gate propertygrp_delete(delete_info_t *dip, const delete_ent_t *ent)
3007c478bd9Sstevel@tonic-gate {
3017c478bd9Sstevel@tonic-gate 	uint32_t be = ent->de_backend;
3027c478bd9Sstevel@tonic-gate 	backend_query_t *q;
3037c478bd9Sstevel@tonic-gate 	uint32_t gen;
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	int r;
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate 	backend_tx_t *tx = (be == BACKEND_TYPE_NORMAL)? dip->di_tx :
3087c478bd9Sstevel@tonic-gate 	    dip->di_np_tx;
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
3117c478bd9Sstevel@tonic-gate 	backend_query_add(q,
3127c478bd9Sstevel@tonic-gate 	    "SELECT pg_gen_id FROM pg_tbl WHERE pg_id = %d; "
3137c478bd9Sstevel@tonic-gate 	    "DELETE FROM pg_tbl WHERE pg_id = %d",
3147c478bd9Sstevel@tonic-gate 	    ent->de_id, ent->de_id);
3157c478bd9Sstevel@tonic-gate 	r = backend_tx_run_single_int(tx, q, &gen);
3167c478bd9Sstevel@tonic-gate 	backend_query_free(q);
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	if (r != REP_PROTOCOL_SUCCESS)
3197c478bd9Sstevel@tonic-gate 		return (r);
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 	return (delete_stack_push(dip, be, &pg_lnk_tbl_delete,
3227c478bd9Sstevel@tonic-gate 	    ent->de_id, gen));
3237c478bd9Sstevel@tonic-gate }
3247c478bd9Sstevel@tonic-gate 
3257c478bd9Sstevel@tonic-gate static int
snaplevel_lnk_delete(delete_info_t * dip,const delete_ent_t * ent)3267c478bd9Sstevel@tonic-gate snaplevel_lnk_delete(delete_info_t *dip, const delete_ent_t *ent)
3277c478bd9Sstevel@tonic-gate {
3287c478bd9Sstevel@tonic-gate 	uint32_t be = ent->de_backend;
3297c478bd9Sstevel@tonic-gate 	backend_query_t *q;
3307c478bd9Sstevel@tonic-gate 	struct delete_cb_info info;
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	int r;
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	backend_tx_t *tx = (be == BACKEND_TYPE_NORMAL)? dip->di_tx :
3357c478bd9Sstevel@tonic-gate 	    dip->di_np_tx;
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	info.dci_dip = dip;
3387c478bd9Sstevel@tonic-gate 	info.dci_be = be;
3397c478bd9Sstevel@tonic-gate 	info.dci_cb = &pg_lnk_tbl_delete;
3407c478bd9Sstevel@tonic-gate 	info.dci_result = REP_PROTOCOL_SUCCESS;
3417c478bd9Sstevel@tonic-gate 
3427c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
3437c478bd9Sstevel@tonic-gate 	backend_query_add(q,
3447c478bd9Sstevel@tonic-gate 	    "SELECT snaplvl_pg_id, snaplvl_gen_id "
3457c478bd9Sstevel@tonic-gate 	    "    FROM snaplevel_lnk_tbl "
3467c478bd9Sstevel@tonic-gate 	    "    WHERE snaplvl_level_id = %d; "
3477c478bd9Sstevel@tonic-gate 	    "DELETE FROM snaplevel_lnk_tbl WHERE snaplvl_level_id = %d",
3487c478bd9Sstevel@tonic-gate 	    ent->de_id, ent->de_id);
3497c478bd9Sstevel@tonic-gate 	r = backend_tx_run(tx, q, push_delete_callback, &info);
3507c478bd9Sstevel@tonic-gate 	backend_query_free(q);
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	if (r == REP_PROTOCOL_DONE) {
3537c478bd9Sstevel@tonic-gate 		assert(info.dci_result != REP_PROTOCOL_SUCCESS);
3547c478bd9Sstevel@tonic-gate 		return (info.dci_result);
3557c478bd9Sstevel@tonic-gate 	}
3567c478bd9Sstevel@tonic-gate 	return (r);
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate static int
snaplevel_tbl_delete(delete_info_t * dip,const delete_ent_t * ent)3607c478bd9Sstevel@tonic-gate snaplevel_tbl_delete(delete_info_t *dip, const delete_ent_t *ent)
3617c478bd9Sstevel@tonic-gate {
3627c478bd9Sstevel@tonic-gate 	uint32_t be = ent->de_backend;
3637c478bd9Sstevel@tonic-gate 	backend_tx_t *tx = (be == BACKEND_TYPE_NORMAL)? dip->di_tx :
3647c478bd9Sstevel@tonic-gate 	    dip->di_np_tx;
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	struct delete_cb_info info;
3677c478bd9Sstevel@tonic-gate 	backend_query_t *q;
3687c478bd9Sstevel@tonic-gate 	int r;
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	assert(be == BACKEND_TYPE_NORMAL);
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
3737c478bd9Sstevel@tonic-gate 	backend_query_add(q,
3747c478bd9Sstevel@tonic-gate 	    "SELECT 1 FROM snapshot_lnk_tbl WHERE lnk_snap_id = %d",
3757c478bd9Sstevel@tonic-gate 	    ent->de_id);
3767c478bd9Sstevel@tonic-gate 	r = backend_tx_run(tx, q, backend_fail_if_seen, NULL);
3777c478bd9Sstevel@tonic-gate 	backend_query_free(q);
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 	if (r == REP_PROTOCOL_DONE)
3807c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_SUCCESS);		/* still in use */
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	info.dci_dip = dip;
3837c478bd9Sstevel@tonic-gate 	info.dci_be = be;
3847c478bd9Sstevel@tonic-gate 	info.dci_cb = &snaplevel_lnk_delete;
3857c478bd9Sstevel@tonic-gate 	info.dci_result = REP_PROTOCOL_SUCCESS;
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
3887c478bd9Sstevel@tonic-gate 	backend_query_add(q,
3897c478bd9Sstevel@tonic-gate 	    "SELECT snap_level_id, 0 FROM snaplevel_tbl WHERE snap_id = %d;"
3907c478bd9Sstevel@tonic-gate 	    "DELETE FROM snaplevel_tbl WHERE snap_id = %d",
3917c478bd9Sstevel@tonic-gate 	    ent->de_id, ent->de_id);
3927c478bd9Sstevel@tonic-gate 	r = backend_tx_run(tx, q, push_delete_callback, &info);
3937c478bd9Sstevel@tonic-gate 	backend_query_free(q);
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	if (r == REP_PROTOCOL_DONE) {
3967c478bd9Sstevel@tonic-gate 		assert(info.dci_result != REP_PROTOCOL_SUCCESS);
3977c478bd9Sstevel@tonic-gate 		return (info.dci_result);
3987c478bd9Sstevel@tonic-gate 	}
3997c478bd9Sstevel@tonic-gate 	return (r);
4007c478bd9Sstevel@tonic-gate }
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate static int
snapshot_lnk_delete(delete_info_t * dip,const delete_ent_t * ent)4037c478bd9Sstevel@tonic-gate snapshot_lnk_delete(delete_info_t *dip, const delete_ent_t *ent)
4047c478bd9Sstevel@tonic-gate {
4057c478bd9Sstevel@tonic-gate 	uint32_t be = ent->de_backend;
4067c478bd9Sstevel@tonic-gate 	backend_tx_t *tx = (be == BACKEND_TYPE_NORMAL)? dip->di_tx :
4077c478bd9Sstevel@tonic-gate 	    dip->di_np_tx;
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	backend_query_t *q;
4107c478bd9Sstevel@tonic-gate 	uint32_t snapid;
4117c478bd9Sstevel@tonic-gate 	int r;
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 	assert(be == BACKEND_TYPE_NORMAL);
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
4167c478bd9Sstevel@tonic-gate 	backend_query_add(q,
4177c478bd9Sstevel@tonic-gate 	    "SELECT lnk_snap_id FROM snapshot_lnk_tbl WHERE lnk_id = %d; "
4187c478bd9Sstevel@tonic-gate 	    "DELETE FROM snapshot_lnk_tbl WHERE lnk_id = %d",
4197c478bd9Sstevel@tonic-gate 	    ent->de_id, ent->de_id);
4207c478bd9Sstevel@tonic-gate 	r = backend_tx_run_single_int(tx, q, &snapid);
4217c478bd9Sstevel@tonic-gate 	backend_query_free(q);
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	if (r != REP_PROTOCOL_SUCCESS)
4247c478bd9Sstevel@tonic-gate 		return (r);
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 	return (delete_stack_push(dip, be, &snaplevel_tbl_delete, snapid, 0));
4277c478bd9Sstevel@tonic-gate }
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate static int
pgparent_delete_add_pgs(delete_info_t * dip,uint32_t parent_id)4307c478bd9Sstevel@tonic-gate pgparent_delete_add_pgs(delete_info_t *dip, uint32_t parent_id)
4317c478bd9Sstevel@tonic-gate {
4327c478bd9Sstevel@tonic-gate 	struct delete_cb_info info;
4337c478bd9Sstevel@tonic-gate 	backend_query_t *q;
4347c478bd9Sstevel@tonic-gate 	int r;
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	info.dci_dip = dip;
4377c478bd9Sstevel@tonic-gate 	info.dci_be = BACKEND_TYPE_NORMAL;
4387c478bd9Sstevel@tonic-gate 	info.dci_cb = &propertygrp_delete;
4397c478bd9Sstevel@tonic-gate 	info.dci_result = REP_PROTOCOL_SUCCESS;
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
4427c478bd9Sstevel@tonic-gate 	backend_query_add(q,
4437c478bd9Sstevel@tonic-gate 	    "SELECT pg_id, 0 FROM pg_tbl WHERE pg_parent_id = %d",
4447c478bd9Sstevel@tonic-gate 	    parent_id);
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	r = backend_tx_run(dip->di_tx, q, push_delete_callback, &info);
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 	if (r == REP_PROTOCOL_DONE) {
4497c478bd9Sstevel@tonic-gate 		assert(info.dci_result != REP_PROTOCOL_SUCCESS);
4507c478bd9Sstevel@tonic-gate 		backend_query_free(q);
4517c478bd9Sstevel@tonic-gate 		return (info.dci_result);
4527c478bd9Sstevel@tonic-gate 	}
4537c478bd9Sstevel@tonic-gate 	if (r != REP_PROTOCOL_SUCCESS) {
4547c478bd9Sstevel@tonic-gate 		backend_query_free(q);
4557c478bd9Sstevel@tonic-gate 		return (r);
4567c478bd9Sstevel@tonic-gate 	}
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	if (dip->di_np_tx != NULL) {
4597c478bd9Sstevel@tonic-gate 		info.dci_be = BACKEND_TYPE_NONPERSIST;
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 		r = backend_tx_run(dip->di_np_tx, q, push_delete_callback,
4627c478bd9Sstevel@tonic-gate 		    &info);
4637c478bd9Sstevel@tonic-gate 
4647c478bd9Sstevel@tonic-gate 		if (r == REP_PROTOCOL_DONE) {
4657c478bd9Sstevel@tonic-gate 			assert(info.dci_result != REP_PROTOCOL_SUCCESS);
4667c478bd9Sstevel@tonic-gate 			backend_query_free(q);
4677c478bd9Sstevel@tonic-gate 			return (info.dci_result);
4687c478bd9Sstevel@tonic-gate 		}
4697c478bd9Sstevel@tonic-gate 		if (r != REP_PROTOCOL_SUCCESS) {
4707c478bd9Sstevel@tonic-gate 			backend_query_free(q);
4717c478bd9Sstevel@tonic-gate 			return (r);
4727c478bd9Sstevel@tonic-gate 		}
4737c478bd9Sstevel@tonic-gate 	}
4747c478bd9Sstevel@tonic-gate 	backend_query_free(q);
4757c478bd9Sstevel@tonic-gate 	return (REP_PROTOCOL_SUCCESS);
4767c478bd9Sstevel@tonic-gate }
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate static int
service_delete(delete_info_t * dip,const delete_ent_t * ent)4797c478bd9Sstevel@tonic-gate service_delete(delete_info_t *dip, const delete_ent_t *ent)
4807c478bd9Sstevel@tonic-gate {
4817c478bd9Sstevel@tonic-gate 	int r;
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate 	r = backend_tx_run_update_changed(dip->di_tx,
4847c478bd9Sstevel@tonic-gate 	    "DELETE FROM service_tbl WHERE svc_id = %d", ent->de_id);
4857c478bd9Sstevel@tonic-gate 	if (r != REP_PROTOCOL_SUCCESS)
4867c478bd9Sstevel@tonic-gate 		return (r);
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	return (pgparent_delete_add_pgs(dip, ent->de_id));
4897c478bd9Sstevel@tonic-gate }
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate static int
instance_delete(delete_info_t * dip,const delete_ent_t * ent)4927c478bd9Sstevel@tonic-gate instance_delete(delete_info_t *dip, const delete_ent_t *ent)
4937c478bd9Sstevel@tonic-gate {
4947c478bd9Sstevel@tonic-gate 	struct delete_cb_info info;
4957c478bd9Sstevel@tonic-gate 	int r;
4967c478bd9Sstevel@tonic-gate 	backend_query_t *q;
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	r = backend_tx_run_update_changed(dip->di_tx,
4997c478bd9Sstevel@tonic-gate 	    "DELETE FROM instance_tbl WHERE instance_id = %d", ent->de_id);
5007c478bd9Sstevel@tonic-gate 	if (r != REP_PROTOCOL_SUCCESS)
5017c478bd9Sstevel@tonic-gate 		return (r);
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 	r = pgparent_delete_add_pgs(dip, ent->de_id);
5047c478bd9Sstevel@tonic-gate 	if (r != REP_PROTOCOL_SUCCESS)
5057c478bd9Sstevel@tonic-gate 		return (r);
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 	info.dci_dip = dip;
5087c478bd9Sstevel@tonic-gate 	info.dci_be = BACKEND_TYPE_NORMAL;
5097c478bd9Sstevel@tonic-gate 	info.dci_cb = &snapshot_lnk_delete;
5107c478bd9Sstevel@tonic-gate 	info.dci_result = REP_PROTOCOL_SUCCESS;
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
5137c478bd9Sstevel@tonic-gate 	backend_query_add(q,
5147c478bd9Sstevel@tonic-gate 	    "SELECT lnk_id, 0 FROM snapshot_lnk_tbl WHERE lnk_inst_id = %d",
5157c478bd9Sstevel@tonic-gate 	    ent->de_id);
5167c478bd9Sstevel@tonic-gate 	r = backend_tx_run(dip->di_tx, q, push_delete_callback, &info);
5177c478bd9Sstevel@tonic-gate 	backend_query_free(q);
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	if (r == REP_PROTOCOL_DONE) {
5207c478bd9Sstevel@tonic-gate 		assert(info.dci_result != REP_PROTOCOL_SUCCESS);
5217c478bd9Sstevel@tonic-gate 		return (info.dci_result);
5227c478bd9Sstevel@tonic-gate 	}
5237c478bd9Sstevel@tonic-gate 	return (r);
5247c478bd9Sstevel@tonic-gate }
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5277c478bd9Sstevel@tonic-gate static int
fill_child_callback(void * data,int columns,char ** vals,char ** names)5287c478bd9Sstevel@tonic-gate fill_child_callback(void *data, int columns, char **vals, char **names)
5297c478bd9Sstevel@tonic-gate {
5307c478bd9Sstevel@tonic-gate 	child_info_t *cp = data;
5317c478bd9Sstevel@tonic-gate 	rc_node_t *np;
5327c478bd9Sstevel@tonic-gate 	uint32_t main_id;
5337c478bd9Sstevel@tonic-gate 	const char *name;
5347c478bd9Sstevel@tonic-gate 	const char *cur;
5357c478bd9Sstevel@tonic-gate 	rc_node_lookup_t *lp = &cp->ci_base_nl;
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	assert(columns == 2);
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 	name = *vals++;
5407c478bd9Sstevel@tonic-gate 	columns--;
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	cur = *vals++;
5437c478bd9Sstevel@tonic-gate 	columns--;
5448918dff3Sjwadams 	string_to_id(cur, &main_id, "id");
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 	lp->rl_main_id = main_id;
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 	if ((np = rc_node_alloc()) == NULL)
5497c478bd9Sstevel@tonic-gate 		return (BACKEND_CALLBACK_ABORT);
5507c478bd9Sstevel@tonic-gate 
5517c478bd9Sstevel@tonic-gate 	np = rc_node_setup(np, lp, name, cp->ci_parent);
5527c478bd9Sstevel@tonic-gate 	rc_node_rele(np);
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	return (BACKEND_CALLBACK_CONTINUE);
5557c478bd9Sstevel@tonic-gate }
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5587c478bd9Sstevel@tonic-gate static int
fill_snapshot_callback(void * data,int columns,char ** vals,char ** names)5597c478bd9Sstevel@tonic-gate fill_snapshot_callback(void *data, int columns, char **vals, char **names)
5607c478bd9Sstevel@tonic-gate {
5617c478bd9Sstevel@tonic-gate 	child_info_t *cp = data;
5627c478bd9Sstevel@tonic-gate 	rc_node_t *np;
5637c478bd9Sstevel@tonic-gate 	uint32_t main_id;
5647c478bd9Sstevel@tonic-gate 	uint32_t snap_id;
5657c478bd9Sstevel@tonic-gate 	const char *name;
5667c478bd9Sstevel@tonic-gate 	const char *cur;
5677c478bd9Sstevel@tonic-gate 	const char *snap;
5687c478bd9Sstevel@tonic-gate 	rc_node_lookup_t *lp = &cp->ci_base_nl;
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate 	assert(columns == 3);
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 	name = *vals++;
5737c478bd9Sstevel@tonic-gate 	columns--;
5747c478bd9Sstevel@tonic-gate 
5757c478bd9Sstevel@tonic-gate 	cur = *vals++;
5767c478bd9Sstevel@tonic-gate 	columns--;
5777c478bd9Sstevel@tonic-gate 	snap = *vals++;
5787c478bd9Sstevel@tonic-gate 	columns--;
5798918dff3Sjwadams 
5808918dff3Sjwadams 	string_to_id(cur, &main_id, "lnk_id");
5818918dff3Sjwadams 	string_to_id(snap, &snap_id, "lnk_snap_id");
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	lp->rl_main_id = main_id;
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 	if ((np = rc_node_alloc()) == NULL)
5867c478bd9Sstevel@tonic-gate 		return (BACKEND_CALLBACK_ABORT);
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 	np = rc_node_setup_snapshot(np, lp, name, snap_id, cp->ci_parent);
5897c478bd9Sstevel@tonic-gate 	rc_node_rele(np);
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate 	return (BACKEND_CALLBACK_CONTINUE);
5927c478bd9Sstevel@tonic-gate }
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5957c478bd9Sstevel@tonic-gate static int
fill_pg_callback(void * data,int columns,char ** vals,char ** names)5967c478bd9Sstevel@tonic-gate fill_pg_callback(void *data, int columns, char **vals, char **names)
5977c478bd9Sstevel@tonic-gate {
5987c478bd9Sstevel@tonic-gate 	child_info_t *cip = data;
5997c478bd9Sstevel@tonic-gate 	const char *name;
6007c478bd9Sstevel@tonic-gate 	const char *type;
6017c478bd9Sstevel@tonic-gate 	const char *cur;
6027c478bd9Sstevel@tonic-gate 	uint32_t main_id;
6037c478bd9Sstevel@tonic-gate 	uint32_t flags;
6047c478bd9Sstevel@tonic-gate 	uint32_t gen_id;
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 	rc_node_lookup_t *lp = &cip->ci_base_nl;
6077c478bd9Sstevel@tonic-gate 	rc_node_t *newnode, *pg;
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 	assert(columns == 5);
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate 	name = *vals++;		/* pg_name */
6127c478bd9Sstevel@tonic-gate 	columns--;
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 	cur = *vals++;		/* pg_id */
6157c478bd9Sstevel@tonic-gate 	columns--;
6168918dff3Sjwadams 	string_to_id(cur, &main_id, "pg_id");
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 	lp->rl_main_id = main_id;
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate 	cur = *vals++;		/* pg_gen_id */
6217c478bd9Sstevel@tonic-gate 	columns--;
6228918dff3Sjwadams 	string_to_id(cur, &gen_id, "pg_gen_id");
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 	type = *vals++;		/* pg_type */
6257c478bd9Sstevel@tonic-gate 	columns--;
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	cur = *vals++;		/* pg_flags */
6287c478bd9Sstevel@tonic-gate 	columns--;
6298918dff3Sjwadams 	string_to_id(cur, &flags, "pg_flags");
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 	if ((newnode = rc_node_alloc()) == NULL)
6327c478bd9Sstevel@tonic-gate 		return (BACKEND_CALLBACK_ABORT);
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 	pg = rc_node_setup_pg(newnode, lp, name, type, flags, gen_id,
6357c478bd9Sstevel@tonic-gate 	    cip->ci_parent);
6367c478bd9Sstevel@tonic-gate 	if (pg == NULL) {
6377c478bd9Sstevel@tonic-gate 		rc_node_destroy(newnode);
6387c478bd9Sstevel@tonic-gate 		return (BACKEND_CALLBACK_ABORT);
6397c478bd9Sstevel@tonic-gate 	}
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	rc_node_rele(pg);
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 	return (BACKEND_CALLBACK_CONTINUE);
6447c478bd9Sstevel@tonic-gate }
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate struct property_value_info {
6477c478bd9Sstevel@tonic-gate 	char		*pvi_base;
6487c478bd9Sstevel@tonic-gate 	size_t		pvi_pos;
6497c478bd9Sstevel@tonic-gate 	size_t		pvi_size;
6507c478bd9Sstevel@tonic-gate 	size_t		pvi_count;
6517c478bd9Sstevel@tonic-gate };
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6547c478bd9Sstevel@tonic-gate static int
property_value_size_cb(void * data,int columns,char ** vals,char ** names)6557c478bd9Sstevel@tonic-gate property_value_size_cb(void *data, int columns, char **vals, char **names)
6567c478bd9Sstevel@tonic-gate {
6577c478bd9Sstevel@tonic-gate 	struct property_value_info *info = data;
6587c478bd9Sstevel@tonic-gate 	assert(columns == 1);
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 	info->pvi_size += strlen(vals[0]) + 1;		/* count the '\0' */
6617c478bd9Sstevel@tonic-gate 
6627c478bd9Sstevel@tonic-gate 	return (BACKEND_CALLBACK_CONTINUE);
6637c478bd9Sstevel@tonic-gate }
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6667c478bd9Sstevel@tonic-gate static int
property_value_cb(void * data,int columns,char ** vals,char ** names)6677c478bd9Sstevel@tonic-gate property_value_cb(void *data, int columns, char **vals, char **names)
6687c478bd9Sstevel@tonic-gate {
6697c478bd9Sstevel@tonic-gate 	struct property_value_info *info = data;
6707c478bd9Sstevel@tonic-gate 	size_t pos, left, len;
6717c478bd9Sstevel@tonic-gate 
6727c478bd9Sstevel@tonic-gate 	assert(columns == 1);
6737c478bd9Sstevel@tonic-gate 	pos = info->pvi_pos;
6747c478bd9Sstevel@tonic-gate 	left = info->pvi_size - pos;
6757c478bd9Sstevel@tonic-gate 
6767c478bd9Sstevel@tonic-gate 	pos = info->pvi_pos;
6777c478bd9Sstevel@tonic-gate 	left = info->pvi_size - pos;
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate 	if ((len = strlcpy(&info->pvi_base[pos], vals[0], left)) >= left) {
6807c478bd9Sstevel@tonic-gate 		/*
6817c478bd9Sstevel@tonic-gate 		 * since we preallocated, above, this shouldn't happen
6827c478bd9Sstevel@tonic-gate 		 */
6837c478bd9Sstevel@tonic-gate 		backend_panic("unexpected database change");
6847c478bd9Sstevel@tonic-gate 	}
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 	len += 1;	/* count the '\0' */
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 	info->pvi_pos += len;
6897c478bd9Sstevel@tonic-gate 	info->pvi_count++;
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate 	return (BACKEND_CALLBACK_CONTINUE);
6927c478bd9Sstevel@tonic-gate }
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate /*ARGSUSED*/
6957c478bd9Sstevel@tonic-gate void
object_free_values(const char * vals,uint32_t type,size_t count,size_t size)6967c478bd9Sstevel@tonic-gate object_free_values(const char *vals, uint32_t type, size_t count, size_t size)
6977c478bd9Sstevel@tonic-gate {
6987c478bd9Sstevel@tonic-gate 	if (vals != NULL)
6997c478bd9Sstevel@tonic-gate 		uu_free((void *)vals);
7007c478bd9Sstevel@tonic-gate }
7017c478bd9Sstevel@tonic-gate 
7027c478bd9Sstevel@tonic-gate /*ARGSUSED*/
7037c478bd9Sstevel@tonic-gate static int
fill_property_callback(void * data,int columns,char ** vals,char ** names)7047c478bd9Sstevel@tonic-gate fill_property_callback(void *data, int columns, char **vals, char **names)
7057c478bd9Sstevel@tonic-gate {
7067c478bd9Sstevel@tonic-gate 	child_info_t *cp = data;
7077c478bd9Sstevel@tonic-gate 	backend_tx_t *tx = cp->ci_tx;
7087c478bd9Sstevel@tonic-gate 	uint32_t main_id;
7097c478bd9Sstevel@tonic-gate 	const char *name;
7107c478bd9Sstevel@tonic-gate 	const char *cur;
7117c478bd9Sstevel@tonic-gate 	rep_protocol_value_type_t type;
7127c478bd9Sstevel@tonic-gate 	rc_node_lookup_t *lp = &cp->ci_base_nl;
7137c478bd9Sstevel@tonic-gate 	struct property_value_info info;
7147c478bd9Sstevel@tonic-gate 	int rc;
7157c478bd9Sstevel@tonic-gate 
7167c478bd9Sstevel@tonic-gate 	assert(columns == 4);
7177c478bd9Sstevel@tonic-gate 	assert(tx != NULL);
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate 	info.pvi_base = NULL;
7207c478bd9Sstevel@tonic-gate 	info.pvi_pos = 0;
7217c478bd9Sstevel@tonic-gate 	info.pvi_size = 0;
7227c478bd9Sstevel@tonic-gate 	info.pvi_count = 0;
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate 	name = *vals++;
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 	cur = *vals++;
7278918dff3Sjwadams 	string_to_id(cur, &main_id, "lnk_prop_id");
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 	cur = *vals++;
7307c478bd9Sstevel@tonic-gate 	assert(('a' <= cur[0] && 'z' >= cur[0]) ||
7317c478bd9Sstevel@tonic-gate 	    ('A' <= cur[0] && 'Z' >= cur[0]) &&
7327c478bd9Sstevel@tonic-gate 	    (cur[1] == 0 || ('a' <= cur[1] && 'z' >= cur[1]) ||
7337c478bd9Sstevel@tonic-gate 	    ('A' <= cur[1] && 'Z' >= cur[1])));
7347c478bd9Sstevel@tonic-gate 	type = cur[0] | (cur[1] << 8);
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate 	lp->rl_main_id = main_id;
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 	/*
7397c478bd9Sstevel@tonic-gate 	 * fill in the values, if any
7407c478bd9Sstevel@tonic-gate 	 */
7417c478bd9Sstevel@tonic-gate 	if ((cur = *vals++) != NULL) {
7427c478bd9Sstevel@tonic-gate 		rep_protocol_responseid_t r;
7437c478bd9Sstevel@tonic-gate 		backend_query_t *q = backend_query_alloc();
7447c478bd9Sstevel@tonic-gate 
745*6e1d2b42Samaguire 		/*
746*6e1d2b42Samaguire 		 * Ensure that select operation is reflective
747*6e1d2b42Samaguire 		 * of repository schema.  If the repository has
748*6e1d2b42Samaguire 		 * been upgraded,  make use of value ordering
749*6e1d2b42Samaguire 		 * by retrieving values in order using the
750*6e1d2b42Samaguire 		 * value_order column.  Otherwise, simply
751*6e1d2b42Samaguire 		 * run the select with no order specified.
752*6e1d2b42Samaguire 		 * The order-insensitive select is necessary
753*6e1d2b42Samaguire 		 * as on first reboot post-upgrade,  the repository
754*6e1d2b42Samaguire 		 * contents need to be read before the repository
755*6e1d2b42Samaguire 		 * backend is writable (and upgrade is possible).
756*6e1d2b42Samaguire 		 */
757*6e1d2b42Samaguire 		if (backend_is_upgraded(tx)) {
7587c478bd9Sstevel@tonic-gate 			backend_query_add(q,
7597c478bd9Sstevel@tonic-gate 			    "SELECT value_value FROM value_tbl "
760*6e1d2b42Samaguire 			    "WHERE (value_id = '%q') ORDER BY value_order",
761*6e1d2b42Samaguire 			    cur);
762*6e1d2b42Samaguire 		} else {
763*6e1d2b42Samaguire 			backend_query_add(q,
764*6e1d2b42Samaguire 			    "SELECT value_value FROM value_tbl "
765*6e1d2b42Samaguire 			    "WHERE (value_id = '%q')",
766*6e1d2b42Samaguire 			    cur);
767*6e1d2b42Samaguire 		}
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 		switch (r = backend_tx_run(tx, q, property_value_size_cb,
7707c478bd9Sstevel@tonic-gate 		    &info)) {
7717c478bd9Sstevel@tonic-gate 		case REP_PROTOCOL_SUCCESS:
7727c478bd9Sstevel@tonic-gate 			break;
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 		case REP_PROTOCOL_FAIL_NO_RESOURCES:
7757c478bd9Sstevel@tonic-gate 			backend_query_free(q);
7767c478bd9Sstevel@tonic-gate 			return (BACKEND_CALLBACK_ABORT);
7777c478bd9Sstevel@tonic-gate 
7787c478bd9Sstevel@tonic-gate 		case REP_PROTOCOL_DONE:
7797c478bd9Sstevel@tonic-gate 		default:
7807c478bd9Sstevel@tonic-gate 			backend_panic("backend_tx_run() returned %d", r);
7817c478bd9Sstevel@tonic-gate 		}
7827c478bd9Sstevel@tonic-gate 		if (info.pvi_size > 0) {
7837c478bd9Sstevel@tonic-gate 			info.pvi_base = uu_zalloc(info.pvi_size);
7847c478bd9Sstevel@tonic-gate 			if (info.pvi_base == NULL) {
7857c478bd9Sstevel@tonic-gate 				backend_query_free(q);
7867c478bd9Sstevel@tonic-gate 				return (BACKEND_CALLBACK_ABORT);
7877c478bd9Sstevel@tonic-gate 			}
7887c478bd9Sstevel@tonic-gate 			switch (r = backend_tx_run(tx, q, property_value_cb,
7897c478bd9Sstevel@tonic-gate 			    &info)) {
7907c478bd9Sstevel@tonic-gate 			case REP_PROTOCOL_SUCCESS:
7917c478bd9Sstevel@tonic-gate 				break;
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 			case REP_PROTOCOL_FAIL_NO_RESOURCES:
7947c478bd9Sstevel@tonic-gate 				uu_free(info.pvi_base);
7957c478bd9Sstevel@tonic-gate 				backend_query_free(q);
7967c478bd9Sstevel@tonic-gate 				return (BACKEND_CALLBACK_ABORT);
7977c478bd9Sstevel@tonic-gate 
7987c478bd9Sstevel@tonic-gate 			case REP_PROTOCOL_DONE:
7997c478bd9Sstevel@tonic-gate 			default:
8007c478bd9Sstevel@tonic-gate 				backend_panic("backend_tx_run() returned %d",
8017c478bd9Sstevel@tonic-gate 				    r);
8027c478bd9Sstevel@tonic-gate 			}
8037c478bd9Sstevel@tonic-gate 		}
8047c478bd9Sstevel@tonic-gate 		backend_query_free(q);
8057c478bd9Sstevel@tonic-gate 	}
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate 	rc = rc_node_create_property(cp->ci_parent, lp, name, type,
8087c478bd9Sstevel@tonic-gate 	    info.pvi_base, info.pvi_count, info.pvi_size);
8097c478bd9Sstevel@tonic-gate 	if (rc != REP_PROTOCOL_SUCCESS) {
8107c478bd9Sstevel@tonic-gate 		assert(rc == REP_PROTOCOL_FAIL_NO_RESOURCES);
8117c478bd9Sstevel@tonic-gate 		return (BACKEND_CALLBACK_ABORT);
8127c478bd9Sstevel@tonic-gate 	}
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 	return (BACKEND_CALLBACK_CONTINUE);
8157c478bd9Sstevel@tonic-gate }
8167c478bd9Sstevel@tonic-gate 
8177c478bd9Sstevel@tonic-gate /*
8187c478bd9Sstevel@tonic-gate  * The *_setup_child_info() functions fill in a child_info_t structure with the
8197c478bd9Sstevel@tonic-gate  * information for the children of np with type type.
8207c478bd9Sstevel@tonic-gate  *
8217c478bd9Sstevel@tonic-gate  * They fail with
8227c478bd9Sstevel@tonic-gate  *   _TYPE_MISMATCH - object cannot have children of type type
8237c478bd9Sstevel@tonic-gate  */
8247c478bd9Sstevel@tonic-gate 
8257c478bd9Sstevel@tonic-gate static int
scope_setup_child_info(rc_node_t * np,uint32_t type,child_info_t * cip)8267c478bd9Sstevel@tonic-gate scope_setup_child_info(rc_node_t *np, uint32_t type, child_info_t *cip)
8277c478bd9Sstevel@tonic-gate {
8287c478bd9Sstevel@tonic-gate 	if (type != REP_PROTOCOL_ENTITY_SERVICE)
8297c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 	bzero(cip, sizeof (*cip));
8327c478bd9Sstevel@tonic-gate 	cip->ci_parent = np;
8337c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_type = type;
8347c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_backend = np->rn_id.rl_backend;
8357c478bd9Sstevel@tonic-gate 	return (REP_PROTOCOL_SUCCESS);
8367c478bd9Sstevel@tonic-gate }
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate static int
service_setup_child_info(rc_node_t * np,uint32_t type,child_info_t * cip)8397c478bd9Sstevel@tonic-gate service_setup_child_info(rc_node_t *np, uint32_t type, child_info_t *cip)
8407c478bd9Sstevel@tonic-gate {
8417c478bd9Sstevel@tonic-gate 	switch (type) {
8427c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_ENTITY_INSTANCE:
8437c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_ENTITY_PROPERTYGRP:
8447c478bd9Sstevel@tonic-gate 		break;
8457c478bd9Sstevel@tonic-gate 	default:
8467c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
8477c478bd9Sstevel@tonic-gate 	}
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 	bzero(cip, sizeof (*cip));
8507c478bd9Sstevel@tonic-gate 	cip->ci_parent = np;
8517c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_type = type;
8527c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_backend = np->rn_id.rl_backend;
8537c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_ids[ID_SERVICE] = np->rn_id.rl_main_id;
8547c478bd9Sstevel@tonic-gate 
8557c478bd9Sstevel@tonic-gate 	return (REP_PROTOCOL_SUCCESS);
8567c478bd9Sstevel@tonic-gate }
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate static int
instance_setup_child_info(rc_node_t * np,uint32_t type,child_info_t * cip)8597c478bd9Sstevel@tonic-gate instance_setup_child_info(rc_node_t *np, uint32_t type, child_info_t *cip)
8607c478bd9Sstevel@tonic-gate {
8617c478bd9Sstevel@tonic-gate 	switch (type) {
8627c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_ENTITY_PROPERTYGRP:
8637c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_ENTITY_SNAPSHOT:
8647c478bd9Sstevel@tonic-gate 		break;
8657c478bd9Sstevel@tonic-gate 	default:
8667c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
8677c478bd9Sstevel@tonic-gate 	}
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate 	bzero(cip, sizeof (*cip));
8707c478bd9Sstevel@tonic-gate 	cip->ci_parent = np;
8717c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_type = type;
8727c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_backend = np->rn_id.rl_backend;
8737c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_ids[ID_SERVICE] = np->rn_id.rl_ids[ID_SERVICE];
8747c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_ids[ID_INSTANCE] = np->rn_id.rl_main_id;
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate 	return (REP_PROTOCOL_SUCCESS);
8777c478bd9Sstevel@tonic-gate }
8787c478bd9Sstevel@tonic-gate 
8797c478bd9Sstevel@tonic-gate static int
snaplevel_setup_child_info(rc_node_t * np,uint32_t type,child_info_t * cip)8807c478bd9Sstevel@tonic-gate snaplevel_setup_child_info(rc_node_t *np, uint32_t type, child_info_t *cip)
8817c478bd9Sstevel@tonic-gate {
8827c478bd9Sstevel@tonic-gate 	if (type != REP_PROTOCOL_ENTITY_PROPERTYGRP)
8837c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
8847c478bd9Sstevel@tonic-gate 
8857c478bd9Sstevel@tonic-gate 	bzero(cip, sizeof (*cip));
8867c478bd9Sstevel@tonic-gate 	cip->ci_parent = np;
8877c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_type = type;
8887c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_backend = np->rn_id.rl_backend;
8897c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_ids[ID_SERVICE] = np->rn_id.rl_ids[ID_SERVICE];
8907c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_ids[ID_INSTANCE] = np->rn_id.rl_ids[ID_INSTANCE];
8917c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_ids[ID_NAME] = np->rn_id.rl_ids[ID_NAME];
8927c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_ids[ID_SNAPSHOT] = np->rn_id.rl_ids[ID_SNAPSHOT];
8937c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_ids[ID_LEVEL] = np->rn_id.rl_main_id;
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate 	return (REP_PROTOCOL_SUCCESS);
8967c478bd9Sstevel@tonic-gate }
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate static int
propertygrp_setup_child_info(rc_node_t * pg,uint32_t type,child_info_t * cip)8997c478bd9Sstevel@tonic-gate propertygrp_setup_child_info(rc_node_t *pg, uint32_t type, child_info_t *cip)
9007c478bd9Sstevel@tonic-gate {
9017c478bd9Sstevel@tonic-gate 	if (type != REP_PROTOCOL_ENTITY_PROPERTY)
9027c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 	bzero(cip, sizeof (*cip));
9057c478bd9Sstevel@tonic-gate 	cip->ci_parent = pg;
9067c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_type = type;
9077c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_backend = pg->rn_id.rl_backend;
9087c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_ids[ID_SERVICE] = pg->rn_id.rl_ids[ID_SERVICE];
9097c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_ids[ID_INSTANCE] = pg->rn_id.rl_ids[ID_INSTANCE];
9107c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_ids[ID_PG] = pg->rn_id.rl_main_id;
9117c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_ids[ID_GEN] = pg->rn_gen_id;
9127c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_ids[ID_NAME] = pg->rn_id.rl_ids[ID_NAME];
9137c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_ids[ID_SNAPSHOT] = pg->rn_id.rl_ids[ID_SNAPSHOT];
9147c478bd9Sstevel@tonic-gate 	cip->ci_base_nl.rl_ids[ID_LEVEL] = pg->rn_id.rl_ids[ID_LEVEL];
9157c478bd9Sstevel@tonic-gate 
9167c478bd9Sstevel@tonic-gate 	return (REP_PROTOCOL_SUCCESS);
9177c478bd9Sstevel@tonic-gate }
9187c478bd9Sstevel@tonic-gate 
9197c478bd9Sstevel@tonic-gate /*
9207c478bd9Sstevel@tonic-gate  * The *_fill_children() functions populate the children of the given rc_node_t
9217c478bd9Sstevel@tonic-gate  * by querying the database and calling rc_node_setup_*() functions (usually
9227c478bd9Sstevel@tonic-gate  * via a fill_*_callback()).
9237c478bd9Sstevel@tonic-gate  *
9247c478bd9Sstevel@tonic-gate  * They fail with
9257c478bd9Sstevel@tonic-gate  *   _NO_RESOURCES
9267c478bd9Sstevel@tonic-gate  */
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate /*
9297c478bd9Sstevel@tonic-gate  * Returns
9307c478bd9Sstevel@tonic-gate  *   _NO_RESOURCES
9317c478bd9Sstevel@tonic-gate  *   _SUCCESS
9327c478bd9Sstevel@tonic-gate  */
9337c478bd9Sstevel@tonic-gate static int
scope_fill_children(rc_node_t * np)9347c478bd9Sstevel@tonic-gate scope_fill_children(rc_node_t *np)
9357c478bd9Sstevel@tonic-gate {
9367c478bd9Sstevel@tonic-gate 	backend_query_t *q;
9377c478bd9Sstevel@tonic-gate 	child_info_t ci;
9387c478bd9Sstevel@tonic-gate 	int res;
9397c478bd9Sstevel@tonic-gate 
9407c478bd9Sstevel@tonic-gate 	(void) scope_setup_child_info(np, REP_PROTOCOL_ENTITY_SERVICE, &ci);
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
9437c478bd9Sstevel@tonic-gate 	backend_query_append(q, "SELECT svc_name, svc_id FROM service_tbl");
9447c478bd9Sstevel@tonic-gate 	res = backend_run(BACKEND_TYPE_NORMAL, q, fill_child_callback, &ci);
9457c478bd9Sstevel@tonic-gate 	backend_query_free(q);
9467c478bd9Sstevel@tonic-gate 
9477c478bd9Sstevel@tonic-gate 	if (res == REP_PROTOCOL_DONE)
9487c478bd9Sstevel@tonic-gate 		res = REP_PROTOCOL_FAIL_NO_RESOURCES;
9497c478bd9Sstevel@tonic-gate 	return (res);
9507c478bd9Sstevel@tonic-gate }
9517c478bd9Sstevel@tonic-gate 
9527c478bd9Sstevel@tonic-gate /*
9537c478bd9Sstevel@tonic-gate  * Returns
9547c478bd9Sstevel@tonic-gate  *   _NO_RESOURCES
9557c478bd9Sstevel@tonic-gate  *   _SUCCESS
9567c478bd9Sstevel@tonic-gate  */
9577c478bd9Sstevel@tonic-gate static int
service_fill_children(rc_node_t * np)9587c478bd9Sstevel@tonic-gate service_fill_children(rc_node_t *np)
9597c478bd9Sstevel@tonic-gate {
9607c478bd9Sstevel@tonic-gate 	backend_query_t *q;
9617c478bd9Sstevel@tonic-gate 	child_info_t ci;
9627c478bd9Sstevel@tonic-gate 	int res;
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate 	assert(np->rn_id.rl_backend == BACKEND_TYPE_NORMAL);
9657c478bd9Sstevel@tonic-gate 
9667c478bd9Sstevel@tonic-gate 	(void) service_setup_child_info(np, REP_PROTOCOL_ENTITY_INSTANCE, &ci);
9677c478bd9Sstevel@tonic-gate 
9687c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
9697c478bd9Sstevel@tonic-gate 	backend_query_add(q,
9707c478bd9Sstevel@tonic-gate 	    "SELECT instance_name, instance_id FROM instance_tbl"
9717c478bd9Sstevel@tonic-gate 	    "    WHERE (instance_svc = %d)",
9727c478bd9Sstevel@tonic-gate 	    np->rn_id.rl_main_id);
9737c478bd9Sstevel@tonic-gate 	res = backend_run(BACKEND_TYPE_NORMAL, q, fill_child_callback, &ci);
9747c478bd9Sstevel@tonic-gate 	backend_query_free(q);
9757c478bd9Sstevel@tonic-gate 
9767c478bd9Sstevel@tonic-gate 	if (res == REP_PROTOCOL_DONE)
9777c478bd9Sstevel@tonic-gate 		res = REP_PROTOCOL_FAIL_NO_RESOURCES;
9787c478bd9Sstevel@tonic-gate 	if (res != REP_PROTOCOL_SUCCESS)
9797c478bd9Sstevel@tonic-gate 		return (res);
9807c478bd9Sstevel@tonic-gate 
9817c478bd9Sstevel@tonic-gate 	(void) service_setup_child_info(np, REP_PROTOCOL_ENTITY_PROPERTYGRP,
9827c478bd9Sstevel@tonic-gate 	    &ci);
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
9857c478bd9Sstevel@tonic-gate 	backend_query_add(q,
9867c478bd9Sstevel@tonic-gate 	    "SELECT pg_name, pg_id, pg_gen_id, pg_type, pg_flags FROM pg_tbl"
9877c478bd9Sstevel@tonic-gate 	    "    WHERE (pg_parent_id = %d)",
9887c478bd9Sstevel@tonic-gate 	    np->rn_id.rl_main_id);
9897c478bd9Sstevel@tonic-gate 
9907c478bd9Sstevel@tonic-gate 	ci.ci_base_nl.rl_backend = BACKEND_TYPE_NORMAL;
9917c478bd9Sstevel@tonic-gate 	res = backend_run(BACKEND_TYPE_NORMAL, q, fill_pg_callback, &ci);
9927c478bd9Sstevel@tonic-gate 	if (res == REP_PROTOCOL_SUCCESS) {
9937c478bd9Sstevel@tonic-gate 		ci.ci_base_nl.rl_backend = BACKEND_TYPE_NONPERSIST;
9947c478bd9Sstevel@tonic-gate 		res = backend_run(BACKEND_TYPE_NONPERSIST, q,
9957c478bd9Sstevel@tonic-gate 		    fill_pg_callback, &ci);
9967c478bd9Sstevel@tonic-gate 		/* nonpersistant database may not exist */
9977c478bd9Sstevel@tonic-gate 		if (res == REP_PROTOCOL_FAIL_BACKEND_ACCESS)
9987c478bd9Sstevel@tonic-gate 			res = REP_PROTOCOL_SUCCESS;
9997c478bd9Sstevel@tonic-gate 	}
10007c478bd9Sstevel@tonic-gate 	if (res == REP_PROTOCOL_DONE)
10017c478bd9Sstevel@tonic-gate 		res = REP_PROTOCOL_FAIL_NO_RESOURCES;
10027c478bd9Sstevel@tonic-gate 	backend_query_free(q);
10037c478bd9Sstevel@tonic-gate 
10047c478bd9Sstevel@tonic-gate 	return (res);
10057c478bd9Sstevel@tonic-gate }
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate /*
10087c478bd9Sstevel@tonic-gate  * Returns
10097c478bd9Sstevel@tonic-gate  *   _NO_RESOURCES
10107c478bd9Sstevel@tonic-gate  *   _SUCCESS
10117c478bd9Sstevel@tonic-gate  */
10127c478bd9Sstevel@tonic-gate static int
instance_fill_children(rc_node_t * np)10137c478bd9Sstevel@tonic-gate instance_fill_children(rc_node_t *np)
10147c478bd9Sstevel@tonic-gate {
10157c478bd9Sstevel@tonic-gate 	backend_query_t *q;
10167c478bd9Sstevel@tonic-gate 	child_info_t ci;
10177c478bd9Sstevel@tonic-gate 	int res;
10187c478bd9Sstevel@tonic-gate 
10197c478bd9Sstevel@tonic-gate 	assert(np->rn_id.rl_backend == BACKEND_TYPE_NORMAL);
10207c478bd9Sstevel@tonic-gate 
10217c478bd9Sstevel@tonic-gate 	/* Get child property groups */
10227c478bd9Sstevel@tonic-gate 	(void) instance_setup_child_info(np, REP_PROTOCOL_ENTITY_PROPERTYGRP,
10237c478bd9Sstevel@tonic-gate 	    &ci);
10247c478bd9Sstevel@tonic-gate 
10257c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
10267c478bd9Sstevel@tonic-gate 	backend_query_add(q,
10277c478bd9Sstevel@tonic-gate 	    "SELECT pg_name, pg_id, pg_gen_id, pg_type, pg_flags FROM pg_tbl"
10287c478bd9Sstevel@tonic-gate 	    "    WHERE (pg_parent_id = %d)",
10297c478bd9Sstevel@tonic-gate 	    np->rn_id.rl_main_id);
10307c478bd9Sstevel@tonic-gate 	ci.ci_base_nl.rl_backend = BACKEND_TYPE_NORMAL;
10317c478bd9Sstevel@tonic-gate 	res = backend_run(BACKEND_TYPE_NORMAL, q, fill_pg_callback, &ci);
10327c478bd9Sstevel@tonic-gate 	if (res == REP_PROTOCOL_SUCCESS) {
10337c478bd9Sstevel@tonic-gate 		ci.ci_base_nl.rl_backend = BACKEND_TYPE_NONPERSIST;
10347c478bd9Sstevel@tonic-gate 		res = backend_run(BACKEND_TYPE_NONPERSIST, q,
10357c478bd9Sstevel@tonic-gate 		    fill_pg_callback, &ci);
10367c478bd9Sstevel@tonic-gate 		/* nonpersistant database may not exist */
10377c478bd9Sstevel@tonic-gate 		if (res == REP_PROTOCOL_FAIL_BACKEND_ACCESS)
10387c478bd9Sstevel@tonic-gate 			res = REP_PROTOCOL_SUCCESS;
10397c478bd9Sstevel@tonic-gate 	}
10407c478bd9Sstevel@tonic-gate 	if (res == REP_PROTOCOL_DONE)
10417c478bd9Sstevel@tonic-gate 		res = REP_PROTOCOL_FAIL_NO_RESOURCES;
10427c478bd9Sstevel@tonic-gate 	backend_query_free(q);
10437c478bd9Sstevel@tonic-gate 
10447c478bd9Sstevel@tonic-gate 	if (res != REP_PROTOCOL_SUCCESS)
10457c478bd9Sstevel@tonic-gate 		return (res);
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate 	/* Get child snapshots */
10487c478bd9Sstevel@tonic-gate 	(void) instance_setup_child_info(np, REP_PROTOCOL_ENTITY_SNAPSHOT,
10497c478bd9Sstevel@tonic-gate 	    &ci);
10507c478bd9Sstevel@tonic-gate 
10517c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
10527c478bd9Sstevel@tonic-gate 	backend_query_add(q,
10537c478bd9Sstevel@tonic-gate 	    "SELECT lnk_snap_name, lnk_id, lnk_snap_id FROM snapshot_lnk_tbl"
10547c478bd9Sstevel@tonic-gate 	    "    WHERE (lnk_inst_id = %d)",
10557c478bd9Sstevel@tonic-gate 	    np->rn_id.rl_main_id);
10567c478bd9Sstevel@tonic-gate 	res = backend_run(BACKEND_TYPE_NORMAL, q, fill_snapshot_callback, &ci);
10577c478bd9Sstevel@tonic-gate 	if (res == REP_PROTOCOL_DONE)
10587c478bd9Sstevel@tonic-gate 		res = REP_PROTOCOL_FAIL_NO_RESOURCES;
10597c478bd9Sstevel@tonic-gate 	backend_query_free(q);
10607c478bd9Sstevel@tonic-gate 
10617c478bd9Sstevel@tonic-gate 	return (res);
10627c478bd9Sstevel@tonic-gate }
10637c478bd9Sstevel@tonic-gate 
10647c478bd9Sstevel@tonic-gate /*
10657c478bd9Sstevel@tonic-gate  * Returns
10667c478bd9Sstevel@tonic-gate  *   _NO_RESOURCES
10677c478bd9Sstevel@tonic-gate  *   _SUCCESS
10687c478bd9Sstevel@tonic-gate  */
10697c478bd9Sstevel@tonic-gate static int
snapshot_fill_children(rc_node_t * np)10707c478bd9Sstevel@tonic-gate snapshot_fill_children(rc_node_t *np)
10717c478bd9Sstevel@tonic-gate {
10727c478bd9Sstevel@tonic-gate 	rc_node_t *nnp;
10737c478bd9Sstevel@tonic-gate 	rc_snapshot_t *sp, *oldsp;
10747c478bd9Sstevel@tonic-gate 	rc_snaplevel_t *lvl;
10757c478bd9Sstevel@tonic-gate 	rc_node_lookup_t nl;
10767c478bd9Sstevel@tonic-gate 	int r;
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate 	/* Get the rc_snapshot_t (& its rc_snaplevel_t's). */
10797c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&np->rn_lock);
10807c478bd9Sstevel@tonic-gate 	sp = np->rn_snapshot;
10817c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&np->rn_lock);
10827c478bd9Sstevel@tonic-gate 	if (sp == NULL) {
10837c478bd9Sstevel@tonic-gate 		r = rc_snapshot_get(np->rn_snapshot_id, &sp);
10847c478bd9Sstevel@tonic-gate 		if (r != REP_PROTOCOL_SUCCESS) {
10857c478bd9Sstevel@tonic-gate 			assert(r == REP_PROTOCOL_FAIL_NO_RESOURCES);
10867c478bd9Sstevel@tonic-gate 			return (r);
10877c478bd9Sstevel@tonic-gate 		}
10887c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&np->rn_lock);
10897c478bd9Sstevel@tonic-gate 		oldsp = np->rn_snapshot;
10907c478bd9Sstevel@tonic-gate 		assert(oldsp == NULL || oldsp == sp);
10917c478bd9Sstevel@tonic-gate 		np->rn_snapshot = sp;
10927c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&np->rn_lock);
10937c478bd9Sstevel@tonic-gate 		if (oldsp != NULL)
10947c478bd9Sstevel@tonic-gate 			rc_snapshot_rele(oldsp);
10957c478bd9Sstevel@tonic-gate 	}
10967c478bd9Sstevel@tonic-gate 
10977c478bd9Sstevel@tonic-gate 	bzero(&nl, sizeof (nl));
10987c478bd9Sstevel@tonic-gate 	nl.rl_type = REP_PROTOCOL_ENTITY_SNAPLEVEL;
10997c478bd9Sstevel@tonic-gate 	nl.rl_backend = np->rn_id.rl_backend;
11007c478bd9Sstevel@tonic-gate 	nl.rl_ids[ID_SERVICE] = np->rn_id.rl_ids[ID_SERVICE];
11017c478bd9Sstevel@tonic-gate 	nl.rl_ids[ID_INSTANCE] = np->rn_id.rl_ids[ID_INSTANCE];
11027c478bd9Sstevel@tonic-gate 	nl.rl_ids[ID_NAME] = np->rn_id.rl_main_id;
11037c478bd9Sstevel@tonic-gate 	nl.rl_ids[ID_SNAPSHOT] = np->rn_snapshot_id;
11047c478bd9Sstevel@tonic-gate 
11057c478bd9Sstevel@tonic-gate 	/* Create rc_node_t's for the snapshot's rc_snaplevel_t's. */
11067c478bd9Sstevel@tonic-gate 	for (lvl = sp->rs_levels; lvl != NULL; lvl = lvl->rsl_next) {
11077c478bd9Sstevel@tonic-gate 		nnp = rc_node_alloc();
11087c478bd9Sstevel@tonic-gate 		assert(nnp != NULL);
11097c478bd9Sstevel@tonic-gate 		nl.rl_main_id = lvl->rsl_level_id;
11107c478bd9Sstevel@tonic-gate 		nnp = rc_node_setup_snaplevel(nnp, &nl, lvl, np);
11117c478bd9Sstevel@tonic-gate 		rc_node_rele(nnp);
11127c478bd9Sstevel@tonic-gate 	}
11137c478bd9Sstevel@tonic-gate 
11147c478bd9Sstevel@tonic-gate 	return (REP_PROTOCOL_SUCCESS);
11157c478bd9Sstevel@tonic-gate }
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate /*
11187c478bd9Sstevel@tonic-gate  * Returns
11197c478bd9Sstevel@tonic-gate  *   _NO_RESOURCES
11207c478bd9Sstevel@tonic-gate  *   _SUCCESS
11217c478bd9Sstevel@tonic-gate  */
11227c478bd9Sstevel@tonic-gate static int
snaplevel_fill_children(rc_node_t * np)11237c478bd9Sstevel@tonic-gate snaplevel_fill_children(rc_node_t *np)
11247c478bd9Sstevel@tonic-gate {
11257c478bd9Sstevel@tonic-gate 	rc_snaplevel_t *lvl = np->rn_snaplevel;
11267c478bd9Sstevel@tonic-gate 	child_info_t ci;
11277c478bd9Sstevel@tonic-gate 	int res;
11287c478bd9Sstevel@tonic-gate 	backend_query_t *q;
11297c478bd9Sstevel@tonic-gate 
11307c478bd9Sstevel@tonic-gate 	(void) snaplevel_setup_child_info(np, REP_PROTOCOL_ENTITY_PROPERTYGRP,
11317c478bd9Sstevel@tonic-gate 	    &ci);
11327c478bd9Sstevel@tonic-gate 
11337c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
11347c478bd9Sstevel@tonic-gate 	backend_query_add(q,
11357c478bd9Sstevel@tonic-gate 	    "SELECT snaplvl_pg_name, snaplvl_pg_id, snaplvl_gen_id, "
11367c478bd9Sstevel@tonic-gate 	    "    snaplvl_pg_type, snaplvl_pg_flags "
11377c478bd9Sstevel@tonic-gate 	    "    FROM snaplevel_lnk_tbl "
11387c478bd9Sstevel@tonic-gate 	    "    WHERE (snaplvl_level_id = %d)",
11397c478bd9Sstevel@tonic-gate 	    lvl->rsl_level_id);
11407c478bd9Sstevel@tonic-gate 	res = backend_run(BACKEND_TYPE_NORMAL, q, fill_pg_callback, &ci);
11417c478bd9Sstevel@tonic-gate 	if (res == REP_PROTOCOL_DONE)
11427c478bd9Sstevel@tonic-gate 		res = REP_PROTOCOL_FAIL_NO_RESOURCES;
11437c478bd9Sstevel@tonic-gate 	backend_query_free(q);
11447c478bd9Sstevel@tonic-gate 
11457c478bd9Sstevel@tonic-gate 	return (res);
11467c478bd9Sstevel@tonic-gate }
11477c478bd9Sstevel@tonic-gate 
11487c478bd9Sstevel@tonic-gate /*
11497c478bd9Sstevel@tonic-gate  * Returns
11507c478bd9Sstevel@tonic-gate  *   _NO_RESOURCES
11517c478bd9Sstevel@tonic-gate  *   _SUCCESS
11527c478bd9Sstevel@tonic-gate  */
11537c478bd9Sstevel@tonic-gate static int
propertygrp_fill_children(rc_node_t * np)11547c478bd9Sstevel@tonic-gate propertygrp_fill_children(rc_node_t *np)
11557c478bd9Sstevel@tonic-gate {
11567c478bd9Sstevel@tonic-gate 	backend_query_t *q;
11577c478bd9Sstevel@tonic-gate 	child_info_t ci;
11587c478bd9Sstevel@tonic-gate 	int res;
11597c478bd9Sstevel@tonic-gate 	backend_tx_t *tx;
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate 	backend_type_t backend = np->rn_id.rl_backend;
11627c478bd9Sstevel@tonic-gate 
11637c478bd9Sstevel@tonic-gate 	(void) propertygrp_setup_child_info(np, REP_PROTOCOL_ENTITY_PROPERTY,
11647c478bd9Sstevel@tonic-gate 	    &ci);
11657c478bd9Sstevel@tonic-gate 
11667c478bd9Sstevel@tonic-gate 	res = backend_tx_begin_ro(backend, &tx);
11677c478bd9Sstevel@tonic-gate 	if (res != REP_PROTOCOL_SUCCESS) {
11687c478bd9Sstevel@tonic-gate 		/*
11697c478bd9Sstevel@tonic-gate 		 * If the backend didn't exist, we wouldn't have got this
11707c478bd9Sstevel@tonic-gate 		 * property group.
11717c478bd9Sstevel@tonic-gate 		 */
11727c478bd9Sstevel@tonic-gate 		assert(res != REP_PROTOCOL_FAIL_BACKEND_ACCESS);
11737c478bd9Sstevel@tonic-gate 		return (res);
11747c478bd9Sstevel@tonic-gate 	}
11757c478bd9Sstevel@tonic-gate 
11767c478bd9Sstevel@tonic-gate 	ci.ci_tx = tx;
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
11797c478bd9Sstevel@tonic-gate 	backend_query_add(q,
11807c478bd9Sstevel@tonic-gate 	    "SELECT lnk_prop_name, lnk_prop_id, lnk_prop_type, lnk_val_id "
11817c478bd9Sstevel@tonic-gate 	    "FROM prop_lnk_tbl "
11827c478bd9Sstevel@tonic-gate 	    "WHERE (lnk_pg_id = %d AND lnk_gen_id = %d)",
11837c478bd9Sstevel@tonic-gate 	    np->rn_id.rl_main_id, np->rn_gen_id);
11847c478bd9Sstevel@tonic-gate 	res = backend_tx_run(tx, q, fill_property_callback, &ci);
11857c478bd9Sstevel@tonic-gate 	if (res == REP_PROTOCOL_DONE)
11867c478bd9Sstevel@tonic-gate 		res = REP_PROTOCOL_FAIL_NO_RESOURCES;
11877c478bd9Sstevel@tonic-gate 	backend_query_free(q);
11887c478bd9Sstevel@tonic-gate 	backend_tx_end_ro(tx);
11897c478bd9Sstevel@tonic-gate 
11907c478bd9Sstevel@tonic-gate 	return (res);
11917c478bd9Sstevel@tonic-gate }
11927c478bd9Sstevel@tonic-gate 
11937c478bd9Sstevel@tonic-gate /*
11947c478bd9Sstevel@tonic-gate  * Fails with
11957c478bd9Sstevel@tonic-gate  *   _TYPE_MISMATCH - lp is not for a service
11967c478bd9Sstevel@tonic-gate  *   _INVALID_TYPE - lp has invalid type
11977c478bd9Sstevel@tonic-gate  *   _BAD_REQUEST - name is invalid
11987c478bd9Sstevel@tonic-gate  */
11997c478bd9Sstevel@tonic-gate static int
scope_query_child(backend_query_t * q,rc_node_lookup_t * lp,const char * name)12007c478bd9Sstevel@tonic-gate scope_query_child(backend_query_t *q, rc_node_lookup_t *lp, const char *name)
12017c478bd9Sstevel@tonic-gate {
12027c478bd9Sstevel@tonic-gate 	uint32_t type = lp->rl_type;
12037c478bd9Sstevel@tonic-gate 	int rc;
12047c478bd9Sstevel@tonic-gate 
12057c478bd9Sstevel@tonic-gate 	if (type != REP_PROTOCOL_ENTITY_SERVICE)
12067c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
12077c478bd9Sstevel@tonic-gate 
12087c478bd9Sstevel@tonic-gate 	if ((rc = rc_check_type_name(type, name)) != REP_PROTOCOL_SUCCESS)
12097c478bd9Sstevel@tonic-gate 		return (rc);
12107c478bd9Sstevel@tonic-gate 
12117c478bd9Sstevel@tonic-gate 	backend_query_add(q,
12127c478bd9Sstevel@tonic-gate 	    "SELECT svc_id FROM service_tbl "
12137c478bd9Sstevel@tonic-gate 	    "WHERE svc_name = '%q'",
12147c478bd9Sstevel@tonic-gate 	    name);
12157c478bd9Sstevel@tonic-gate 
12167c478bd9Sstevel@tonic-gate 	return (REP_PROTOCOL_SUCCESS);
12177c478bd9Sstevel@tonic-gate }
12187c478bd9Sstevel@tonic-gate 
12197c478bd9Sstevel@tonic-gate /*
12207c478bd9Sstevel@tonic-gate  * Fails with
12217c478bd9Sstevel@tonic-gate  *   _NO_RESOURCES - out of memory
12227c478bd9Sstevel@tonic-gate  */
12237c478bd9Sstevel@tonic-gate static int
scope_insert_child(backend_tx_t * tx,rc_node_lookup_t * lp,const char * name)12247c478bd9Sstevel@tonic-gate scope_insert_child(backend_tx_t *tx, rc_node_lookup_t *lp, const char *name)
12257c478bd9Sstevel@tonic-gate {
12267c478bd9Sstevel@tonic-gate 	return (backend_tx_run_update(tx,
12277c478bd9Sstevel@tonic-gate 	    "INSERT INTO service_tbl (svc_id, svc_name) "
12287c478bd9Sstevel@tonic-gate 	    "VALUES (%d, '%q')",
12297c478bd9Sstevel@tonic-gate 	    lp->rl_main_id, name));
12307c478bd9Sstevel@tonic-gate }
12317c478bd9Sstevel@tonic-gate 
12327c478bd9Sstevel@tonic-gate /*
12337c478bd9Sstevel@tonic-gate  * Fails with
12347c478bd9Sstevel@tonic-gate  *   _TYPE_MISMATCH - lp is not for an instance or property group
12357c478bd9Sstevel@tonic-gate  *   _INVALID_TYPE - lp has invalid type
12367c478bd9Sstevel@tonic-gate  *   _BAD_REQUEST - name is invalid
12377c478bd9Sstevel@tonic-gate  */
12387c478bd9Sstevel@tonic-gate static int
service_query_child(backend_query_t * q,rc_node_lookup_t * lp,const char * name)12397c478bd9Sstevel@tonic-gate service_query_child(backend_query_t *q, rc_node_lookup_t *lp, const char *name)
12407c478bd9Sstevel@tonic-gate {
12417c478bd9Sstevel@tonic-gate 	uint32_t type = lp->rl_type;
12427c478bd9Sstevel@tonic-gate 	int rc;
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate 	if (type != REP_PROTOCOL_ENTITY_INSTANCE &&
12457c478bd9Sstevel@tonic-gate 	    type != REP_PROTOCOL_ENTITY_PROPERTYGRP)
12467c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
12477c478bd9Sstevel@tonic-gate 
12487c478bd9Sstevel@tonic-gate 	if ((rc = rc_check_type_name(type, name)) != REP_PROTOCOL_SUCCESS)
12497c478bd9Sstevel@tonic-gate 		return (rc);
12507c478bd9Sstevel@tonic-gate 
12517c478bd9Sstevel@tonic-gate 	switch (type) {
12527c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_ENTITY_INSTANCE:
12537c478bd9Sstevel@tonic-gate 		backend_query_add(q,
12547c478bd9Sstevel@tonic-gate 		    "SELECT instance_id FROM instance_tbl "
12557c478bd9Sstevel@tonic-gate 		    "WHERE instance_name = '%q' AND instance_svc = %d",
12567c478bd9Sstevel@tonic-gate 		    name, lp->rl_ids[ID_SERVICE]);
12577c478bd9Sstevel@tonic-gate 		break;
12587c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_ENTITY_PROPERTYGRP:
12597c478bd9Sstevel@tonic-gate 		backend_query_add(q,
12607c478bd9Sstevel@tonic-gate 		    "SELECT pg_id FROM pg_tbl "
12617c478bd9Sstevel@tonic-gate 		    "    WHERE pg_name = '%q' AND pg_parent_id = %d",
12627c478bd9Sstevel@tonic-gate 		    name, lp->rl_ids[ID_SERVICE]);
12637c478bd9Sstevel@tonic-gate 		break;
12647c478bd9Sstevel@tonic-gate 	default:
12657c478bd9Sstevel@tonic-gate 		assert(0);
12667c478bd9Sstevel@tonic-gate 		abort();
12677c478bd9Sstevel@tonic-gate 	}
12687c478bd9Sstevel@tonic-gate 
12697c478bd9Sstevel@tonic-gate 	return (REP_PROTOCOL_SUCCESS);
12707c478bd9Sstevel@tonic-gate }
12717c478bd9Sstevel@tonic-gate 
12727c478bd9Sstevel@tonic-gate /*
12737c478bd9Sstevel@tonic-gate  * Fails with
12747c478bd9Sstevel@tonic-gate  *   _NO_RESOURCES - out of memory
12757c478bd9Sstevel@tonic-gate  */
12767c478bd9Sstevel@tonic-gate static int
service_insert_child(backend_tx_t * tx,rc_node_lookup_t * lp,const char * name)12777c478bd9Sstevel@tonic-gate service_insert_child(backend_tx_t *tx, rc_node_lookup_t *lp, const char *name)
12787c478bd9Sstevel@tonic-gate {
12797c478bd9Sstevel@tonic-gate 	return (backend_tx_run_update(tx,
12807c478bd9Sstevel@tonic-gate 	    "INSERT INTO instance_tbl "
12817c478bd9Sstevel@tonic-gate 	    "    (instance_id, instance_name, instance_svc) "
12827c478bd9Sstevel@tonic-gate 	    "VALUES (%d, '%q', %d)",
12837c478bd9Sstevel@tonic-gate 	    lp->rl_main_id, name, lp->rl_ids[ID_SERVICE]));
12847c478bd9Sstevel@tonic-gate }
12857c478bd9Sstevel@tonic-gate 
12867c478bd9Sstevel@tonic-gate /*
12877c478bd9Sstevel@tonic-gate  * Fails with
12887c478bd9Sstevel@tonic-gate  *   _NO_RESOURCES - out of memory
12897c478bd9Sstevel@tonic-gate  */
12907c478bd9Sstevel@tonic-gate static int
instance_insert_child(backend_tx_t * tx,rc_node_lookup_t * lp,const char * name)12917c478bd9Sstevel@tonic-gate instance_insert_child(backend_tx_t *tx, rc_node_lookup_t *lp, const char *name)
12927c478bd9Sstevel@tonic-gate {
12937c478bd9Sstevel@tonic-gate 	return (backend_tx_run_update(tx,
12947c478bd9Sstevel@tonic-gate 	    "INSERT INTO snapshot_lnk_tbl "
12957c478bd9Sstevel@tonic-gate 	    "    (lnk_id, lnk_inst_id, lnk_snap_name, lnk_snap_id) "
12967c478bd9Sstevel@tonic-gate 	    "VALUES (%d, %d, '%q', 0)",
12977c478bd9Sstevel@tonic-gate 	    lp->rl_main_id, lp->rl_ids[ID_INSTANCE], name));
12987c478bd9Sstevel@tonic-gate }
12997c478bd9Sstevel@tonic-gate 
13007c478bd9Sstevel@tonic-gate /*
13017c478bd9Sstevel@tonic-gate  * Fails with
13027c478bd9Sstevel@tonic-gate  *   _TYPE_MISMATCH - lp is not for a property group or snapshot
13037c478bd9Sstevel@tonic-gate  *   _INVALID_TYPE - lp has invalid type
13047c478bd9Sstevel@tonic-gate  *   _BAD_REQUEST - name is invalid
13057c478bd9Sstevel@tonic-gate  */
13067c478bd9Sstevel@tonic-gate static int
instance_query_child(backend_query_t * q,rc_node_lookup_t * lp,const char * name)13077c478bd9Sstevel@tonic-gate instance_query_child(backend_query_t *q, rc_node_lookup_t *lp, const char *name)
13087c478bd9Sstevel@tonic-gate {
13097c478bd9Sstevel@tonic-gate 	uint32_t type = lp->rl_type;
13107c478bd9Sstevel@tonic-gate 	int rc;
13117c478bd9Sstevel@tonic-gate 
13127c478bd9Sstevel@tonic-gate 	if (type != REP_PROTOCOL_ENTITY_PROPERTYGRP &&
13137c478bd9Sstevel@tonic-gate 	    type != REP_PROTOCOL_ENTITY_SNAPSHOT)
13147c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
13157c478bd9Sstevel@tonic-gate 
13167c478bd9Sstevel@tonic-gate 	if ((rc = rc_check_type_name(type, name)) != REP_PROTOCOL_SUCCESS)
13177c478bd9Sstevel@tonic-gate 		return (rc);
13187c478bd9Sstevel@tonic-gate 
13197c478bd9Sstevel@tonic-gate 	switch (type) {
13207c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_ENTITY_PROPERTYGRP:
13217c478bd9Sstevel@tonic-gate 		backend_query_add(q,
13227c478bd9Sstevel@tonic-gate 		    "SELECT pg_id FROM pg_tbl "
13237c478bd9Sstevel@tonic-gate 		    "    WHERE pg_name = '%q' AND pg_parent_id = %d",
13247c478bd9Sstevel@tonic-gate 		    name, lp->rl_ids[ID_INSTANCE]);
13257c478bd9Sstevel@tonic-gate 		break;
13267c478bd9Sstevel@tonic-gate 	case REP_PROTOCOL_ENTITY_SNAPSHOT:
13277c478bd9Sstevel@tonic-gate 		backend_query_add(q,
13287c478bd9Sstevel@tonic-gate 		    "SELECT lnk_id FROM snapshot_lnk_tbl "
13297c478bd9Sstevel@tonic-gate 		    "    WHERE lnk_snap_name = '%q' AND lnk_inst_id = %d",
13307c478bd9Sstevel@tonic-gate 		    name, lp->rl_ids[ID_INSTANCE]);
13317c478bd9Sstevel@tonic-gate 		break;
13327c478bd9Sstevel@tonic-gate 	default:
13337c478bd9Sstevel@tonic-gate 		assert(0);
13347c478bd9Sstevel@tonic-gate 		abort();
13357c478bd9Sstevel@tonic-gate 	}
13367c478bd9Sstevel@tonic-gate 
13377c478bd9Sstevel@tonic-gate 	return (REP_PROTOCOL_SUCCESS);
13387c478bd9Sstevel@tonic-gate }
13397c478bd9Sstevel@tonic-gate 
13407c478bd9Sstevel@tonic-gate static int
generic_insert_pg_child(backend_tx_t * tx,rc_node_lookup_t * lp,const char * name,const char * pgtype,uint32_t flags,uint32_t gen)13417c478bd9Sstevel@tonic-gate generic_insert_pg_child(backend_tx_t *tx, rc_node_lookup_t *lp,
13427c478bd9Sstevel@tonic-gate     const char *name, const char *pgtype, uint32_t flags, uint32_t gen)
13437c478bd9Sstevel@tonic-gate {
13447c478bd9Sstevel@tonic-gate 	int parent_id = (lp->rl_ids[ID_INSTANCE] != 0)?
13457c478bd9Sstevel@tonic-gate 	    lp->rl_ids[ID_INSTANCE] : lp->rl_ids[ID_SERVICE];
13467c478bd9Sstevel@tonic-gate 	return (backend_tx_run_update(tx,
13477c478bd9Sstevel@tonic-gate 	    "INSERT INTO pg_tbl "
13487c478bd9Sstevel@tonic-gate 	    "    (pg_id, pg_name, pg_parent_id, pg_type, pg_flags, pg_gen_id) "
13497c478bd9Sstevel@tonic-gate 	    "VALUES (%d, '%q', %d, '%q', %d, %d)",
13507c478bd9Sstevel@tonic-gate 	    lp->rl_main_id, name, parent_id, pgtype, flags, gen));
13517c478bd9Sstevel@tonic-gate }
13527c478bd9Sstevel@tonic-gate 
13537c478bd9Sstevel@tonic-gate static int
service_delete_start(rc_node_t * np,delete_info_t * dip)13547c478bd9Sstevel@tonic-gate service_delete_start(rc_node_t *np, delete_info_t *dip)
13557c478bd9Sstevel@tonic-gate {
13567c478bd9Sstevel@tonic-gate 	int r;
13577c478bd9Sstevel@tonic-gate 	backend_query_t *q = backend_query_alloc();
13587c478bd9Sstevel@tonic-gate 
13597c478bd9Sstevel@tonic-gate 	/*
13607c478bd9Sstevel@tonic-gate 	 * Check for child instances, and refuse to delete if they exist.
13617c478bd9Sstevel@tonic-gate 	 */
13627c478bd9Sstevel@tonic-gate 	backend_query_add(q,
13637c478bd9Sstevel@tonic-gate 	    "SELECT 1 FROM instance_tbl WHERE instance_svc = %d",
13647c478bd9Sstevel@tonic-gate 	    np->rn_id.rl_main_id);
13657c478bd9Sstevel@tonic-gate 
13667c478bd9Sstevel@tonic-gate 	r = backend_tx_run(dip->di_tx, q, backend_fail_if_seen, NULL);
13677c478bd9Sstevel@tonic-gate 	backend_query_free(q);
13687c478bd9Sstevel@tonic-gate 
13697c478bd9Sstevel@tonic-gate 	if (r == REP_PROTOCOL_DONE)
13707c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_EXISTS);	/* instances exist */
13717c478bd9Sstevel@tonic-gate 
13727c478bd9Sstevel@tonic-gate 	return (delete_stack_push(dip, BACKEND_TYPE_NORMAL, &service_delete,
13737c478bd9Sstevel@tonic-gate 	    np->rn_id.rl_main_id, 0));
13747c478bd9Sstevel@tonic-gate }
13757c478bd9Sstevel@tonic-gate 
13767c478bd9Sstevel@tonic-gate static int
instance_delete_start(rc_node_t * np,delete_info_t * dip)13777c478bd9Sstevel@tonic-gate instance_delete_start(rc_node_t *np, delete_info_t *dip)
13787c478bd9Sstevel@tonic-gate {
13797c478bd9Sstevel@tonic-gate 	return (delete_stack_push(dip, BACKEND_TYPE_NORMAL, &instance_delete,
13807c478bd9Sstevel@tonic-gate 	    np->rn_id.rl_main_id, 0));
13817c478bd9Sstevel@tonic-gate }
13827c478bd9Sstevel@tonic-gate 
13837c478bd9Sstevel@tonic-gate static int
snapshot_delete_start(rc_node_t * np,delete_info_t * dip)13847c478bd9Sstevel@tonic-gate snapshot_delete_start(rc_node_t *np, delete_info_t *dip)
13857c478bd9Sstevel@tonic-gate {
13867c478bd9Sstevel@tonic-gate 	return (delete_stack_push(dip, BACKEND_TYPE_NORMAL,
13877c478bd9Sstevel@tonic-gate 	    &snapshot_lnk_delete, np->rn_id.rl_main_id, 0));
13887c478bd9Sstevel@tonic-gate }
13897c478bd9Sstevel@tonic-gate 
13907c478bd9Sstevel@tonic-gate static int
propertygrp_delete_start(rc_node_t * np,delete_info_t * dip)13917c478bd9Sstevel@tonic-gate propertygrp_delete_start(rc_node_t *np, delete_info_t *dip)
13927c478bd9Sstevel@tonic-gate {
13937c478bd9Sstevel@tonic-gate 	return (delete_stack_push(dip, np->rn_id.rl_backend,
13947c478bd9Sstevel@tonic-gate 	    &propertygrp_delete, np->rn_id.rl_main_id, 0));
13957c478bd9Sstevel@tonic-gate }
13967c478bd9Sstevel@tonic-gate 
13977c478bd9Sstevel@tonic-gate static object_info_t info[] = {
13987c478bd9Sstevel@tonic-gate 	{REP_PROTOCOL_ENTITY_NONE},
13997c478bd9Sstevel@tonic-gate 	{REP_PROTOCOL_ENTITY_SCOPE,
14007c478bd9Sstevel@tonic-gate 		BACKEND_ID_INVALID,
14017c478bd9Sstevel@tonic-gate 		scope_fill_children,
14027c478bd9Sstevel@tonic-gate 		scope_setup_child_info,
14037c478bd9Sstevel@tonic-gate 		scope_query_child,
14047c478bd9Sstevel@tonic-gate 		scope_insert_child,
14057c478bd9Sstevel@tonic-gate 		NULL,
14067c478bd9Sstevel@tonic-gate 		NULL,
14077c478bd9Sstevel@tonic-gate 	},
14087c478bd9Sstevel@tonic-gate 	{REP_PROTOCOL_ENTITY_SERVICE,
14097c478bd9Sstevel@tonic-gate 		BACKEND_ID_SERVICE_INSTANCE,
14107c478bd9Sstevel@tonic-gate 		service_fill_children,
14117c478bd9Sstevel@tonic-gate 		service_setup_child_info,
14127c478bd9Sstevel@tonic-gate 		service_query_child,
14137c478bd9Sstevel@tonic-gate 		service_insert_child,
14147c478bd9Sstevel@tonic-gate 		generic_insert_pg_child,
14157c478bd9Sstevel@tonic-gate 		service_delete_start,
14167c478bd9Sstevel@tonic-gate 	},
14177c478bd9Sstevel@tonic-gate 	{REP_PROTOCOL_ENTITY_INSTANCE,
14187c478bd9Sstevel@tonic-gate 		BACKEND_ID_SERVICE_INSTANCE,
14197c478bd9Sstevel@tonic-gate 		instance_fill_children,
14207c478bd9Sstevel@tonic-gate 		instance_setup_child_info,
14217c478bd9Sstevel@tonic-gate 		instance_query_child,
14227c478bd9Sstevel@tonic-gate 		instance_insert_child,
14237c478bd9Sstevel@tonic-gate 		generic_insert_pg_child,
14247c478bd9Sstevel@tonic-gate 		instance_delete_start,
14257c478bd9Sstevel@tonic-gate 	},
14267c478bd9Sstevel@tonic-gate 	{REP_PROTOCOL_ENTITY_SNAPSHOT,
14277c478bd9Sstevel@tonic-gate 		BACKEND_ID_SNAPNAME,
14287c478bd9Sstevel@tonic-gate 		snapshot_fill_children,
14297c478bd9Sstevel@tonic-gate 		NULL,
14307c478bd9Sstevel@tonic-gate 		NULL,
14317c478bd9Sstevel@tonic-gate 		NULL,
14327c478bd9Sstevel@tonic-gate 		NULL,
14337c478bd9Sstevel@tonic-gate 		snapshot_delete_start,
14347c478bd9Sstevel@tonic-gate 	},
14357c478bd9Sstevel@tonic-gate 	{REP_PROTOCOL_ENTITY_SNAPLEVEL,
14367c478bd9Sstevel@tonic-gate 		BACKEND_ID_SNAPLEVEL,
14377c478bd9Sstevel@tonic-gate 		snaplevel_fill_children,
14387c478bd9Sstevel@tonic-gate 		snaplevel_setup_child_info,
14397c478bd9Sstevel@tonic-gate 	},
14407c478bd9Sstevel@tonic-gate 	{REP_PROTOCOL_ENTITY_PROPERTYGRP,
14417c478bd9Sstevel@tonic-gate 		BACKEND_ID_PROPERTYGRP,
14427c478bd9Sstevel@tonic-gate 		propertygrp_fill_children,
14437c478bd9Sstevel@tonic-gate 		NULL,
14447c478bd9Sstevel@tonic-gate 		NULL,
14457c478bd9Sstevel@tonic-gate 		NULL,
14467c478bd9Sstevel@tonic-gate 		NULL,
14477c478bd9Sstevel@tonic-gate 		propertygrp_delete_start,
14487c478bd9Sstevel@tonic-gate 	},
14497c478bd9Sstevel@tonic-gate 	{REP_PROTOCOL_ENTITY_PROPERTY},
14507c478bd9Sstevel@tonic-gate 	{-1UL}
14517c478bd9Sstevel@tonic-gate };
14527c478bd9Sstevel@tonic-gate #define	NUM_INFO (sizeof (info) / sizeof (*info))
14537c478bd9Sstevel@tonic-gate 
14547c478bd9Sstevel@tonic-gate /*
14557c478bd9Sstevel@tonic-gate  * object_fill_children() populates the child list of an rc_node_t by calling
14567c478bd9Sstevel@tonic-gate  * the appropriate <type>_fill_children() which runs backend queries that
14577c478bd9Sstevel@tonic-gate  * call an appropriate fill_*_callback() which takes a row of results,
14587c478bd9Sstevel@tonic-gate  * decodes them, and calls an rc_node_setup*() function in rc_node.c to create
14597c478bd9Sstevel@tonic-gate  * a child.
14607c478bd9Sstevel@tonic-gate  *
14617c478bd9Sstevel@tonic-gate  * Fails with
14627c478bd9Sstevel@tonic-gate  *   _NO_RESOURCES
14637c478bd9Sstevel@tonic-gate  */
14647c478bd9Sstevel@tonic-gate int
object_fill_children(rc_node_t * pp)14657c478bd9Sstevel@tonic-gate object_fill_children(rc_node_t *pp)
14667c478bd9Sstevel@tonic-gate {
14677c478bd9Sstevel@tonic-gate 	uint32_t type = pp->rn_id.rl_type;
14687c478bd9Sstevel@tonic-gate 	assert(type > 0 && type < NUM_INFO);
14697c478bd9Sstevel@tonic-gate 
14707c478bd9Sstevel@tonic-gate 	return ((*info[type].obj_fill_children)(pp));
14717c478bd9Sstevel@tonic-gate }
14727c478bd9Sstevel@tonic-gate 
14737c478bd9Sstevel@tonic-gate int
object_delete(rc_node_t * pp)14747c478bd9Sstevel@tonic-gate object_delete(rc_node_t *pp)
14757c478bd9Sstevel@tonic-gate {
14767c478bd9Sstevel@tonic-gate 	int rc;
14777c478bd9Sstevel@tonic-gate 
14787c478bd9Sstevel@tonic-gate 	delete_info_t dip;
14797c478bd9Sstevel@tonic-gate 	delete_ent_t de;
14807c478bd9Sstevel@tonic-gate 
14817c478bd9Sstevel@tonic-gate 	uint32_t type = pp->rn_id.rl_type;
14827c478bd9Sstevel@tonic-gate 	assert(type > 0 && type < NUM_INFO);
14837c478bd9Sstevel@tonic-gate 
14847c478bd9Sstevel@tonic-gate 	if (info[type].obj_delete_start == NULL)
14857c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_BAD_REQUEST);
14867c478bd9Sstevel@tonic-gate 
14877c478bd9Sstevel@tonic-gate 	(void) memset(&dip, '\0', sizeof (dip));
14887c478bd9Sstevel@tonic-gate 	rc = backend_tx_begin(BACKEND_TYPE_NORMAL, &dip.di_tx);
14897c478bd9Sstevel@tonic-gate 	if (rc != REP_PROTOCOL_SUCCESS)
14907c478bd9Sstevel@tonic-gate 		return (rc);
14917c478bd9Sstevel@tonic-gate 
14927c478bd9Sstevel@tonic-gate 	rc = backend_tx_begin(BACKEND_TYPE_NONPERSIST, &dip.di_np_tx);
14937c478bd9Sstevel@tonic-gate 	if (rc == REP_PROTOCOL_FAIL_BACKEND_ACCESS ||
14947c478bd9Sstevel@tonic-gate 	    rc == REP_PROTOCOL_FAIL_BACKEND_READONLY)
14957c478bd9Sstevel@tonic-gate 		dip.di_np_tx = NULL;
14967c478bd9Sstevel@tonic-gate 	else if (rc != REP_PROTOCOL_SUCCESS) {
14977c478bd9Sstevel@tonic-gate 		backend_tx_rollback(dip.di_tx);
14987c478bd9Sstevel@tonic-gate 		return (rc);
14997c478bd9Sstevel@tonic-gate 	}
15007c478bd9Sstevel@tonic-gate 
15017c478bd9Sstevel@tonic-gate 	if ((rc = (*info[type].obj_delete_start)(pp, &dip)) !=
15027c478bd9Sstevel@tonic-gate 	    REP_PROTOCOL_SUCCESS) {
15037c478bd9Sstevel@tonic-gate 		goto fail;
15047c478bd9Sstevel@tonic-gate 	}
15057c478bd9Sstevel@tonic-gate 
15067c478bd9Sstevel@tonic-gate 	while (delete_stack_pop(&dip, &de)) {
15077c478bd9Sstevel@tonic-gate 		rc = (*de.de_cb)(&dip, &de);
15087c478bd9Sstevel@tonic-gate 		if (rc != REP_PROTOCOL_SUCCESS)
15097c478bd9Sstevel@tonic-gate 			goto fail;
15107c478bd9Sstevel@tonic-gate 	}
15117c478bd9Sstevel@tonic-gate 
15127c478bd9Sstevel@tonic-gate 	rc = backend_tx_commit(dip.di_tx);
15137c478bd9Sstevel@tonic-gate 	if (rc != REP_PROTOCOL_SUCCESS)
15147c478bd9Sstevel@tonic-gate 		backend_tx_rollback(dip.di_np_tx);
15157c478bd9Sstevel@tonic-gate 	else if (dip.di_np_tx)
15167c478bd9Sstevel@tonic-gate 		(void) backend_tx_commit(dip.di_np_tx);
15177c478bd9Sstevel@tonic-gate 
15187c478bd9Sstevel@tonic-gate 	delete_stack_cleanup(&dip);
15197c478bd9Sstevel@tonic-gate 
15207c478bd9Sstevel@tonic-gate 	return (rc);
15217c478bd9Sstevel@tonic-gate 
15227c478bd9Sstevel@tonic-gate fail:
15237c478bd9Sstevel@tonic-gate 	backend_tx_rollback(dip.di_tx);
15247c478bd9Sstevel@tonic-gate 	backend_tx_rollback(dip.di_np_tx);
15257c478bd9Sstevel@tonic-gate 	delete_stack_cleanup(&dip);
15267c478bd9Sstevel@tonic-gate 	return (rc);
15277c478bd9Sstevel@tonic-gate }
15287c478bd9Sstevel@tonic-gate 
15297c478bd9Sstevel@tonic-gate int
object_do_create(backend_tx_t * tx,child_info_t * cip,rc_node_t * pp,uint32_t type,const char * name,rc_node_t ** cpp)15307c478bd9Sstevel@tonic-gate object_do_create(backend_tx_t *tx, child_info_t *cip, rc_node_t *pp,
15317c478bd9Sstevel@tonic-gate     uint32_t type, const char *name, rc_node_t **cpp)
15327c478bd9Sstevel@tonic-gate {
15337c478bd9Sstevel@tonic-gate 	uint32_t ptype = pp->rn_id.rl_type;
15347c478bd9Sstevel@tonic-gate 
15357c478bd9Sstevel@tonic-gate 	backend_query_t *q;
15367c478bd9Sstevel@tonic-gate 	uint32_t id;
15377c478bd9Sstevel@tonic-gate 	rc_node_t *np = NULL;
15387c478bd9Sstevel@tonic-gate 	int rc;
15397c478bd9Sstevel@tonic-gate 	object_info_t *ip;
15407c478bd9Sstevel@tonic-gate 
15417c478bd9Sstevel@tonic-gate 	rc_node_lookup_t *lp = &cip->ci_base_nl;
15427c478bd9Sstevel@tonic-gate 
15437c478bd9Sstevel@tonic-gate 	assert(ptype > 0 && ptype < NUM_INFO);
15447c478bd9Sstevel@tonic-gate 
15457c478bd9Sstevel@tonic-gate 	ip = &info[ptype];
15467c478bd9Sstevel@tonic-gate 
15477c478bd9Sstevel@tonic-gate 	if (type == REP_PROTOCOL_ENTITY_PROPERTYGRP)
15487c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_NOT_APPLICABLE);
15497c478bd9Sstevel@tonic-gate 
15507c478bd9Sstevel@tonic-gate 	if (ip->obj_setup_child_info == NULL ||
15517c478bd9Sstevel@tonic-gate 	    ip->obj_query_child == NULL ||
15527c478bd9Sstevel@tonic-gate 	    ip->obj_insert_child == NULL)
15537c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_BAD_REQUEST);
15547c478bd9Sstevel@tonic-gate 
15557c478bd9Sstevel@tonic-gate 	if ((rc = (*ip->obj_setup_child_info)(pp, type, cip)) !=
15567c478bd9Sstevel@tonic-gate 	    REP_PROTOCOL_SUCCESS)
15577c478bd9Sstevel@tonic-gate 		return (rc);
15587c478bd9Sstevel@tonic-gate 
15597c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
15607c478bd9Sstevel@tonic-gate 	if ((rc = (*ip->obj_query_child)(q, lp, name)) !=
15617c478bd9Sstevel@tonic-gate 	    REP_PROTOCOL_SUCCESS) {
15627c478bd9Sstevel@tonic-gate 		assert(rc == REP_PROTOCOL_FAIL_BAD_REQUEST);
15637c478bd9Sstevel@tonic-gate 		backend_query_free(q);
15647c478bd9Sstevel@tonic-gate 		return (rc);
15657c478bd9Sstevel@tonic-gate 	}
15667c478bd9Sstevel@tonic-gate 
15677c478bd9Sstevel@tonic-gate 	rc = backend_tx_run_single_int(tx, q, &id);
15687c478bd9Sstevel@tonic-gate 	backend_query_free(q);
15697c478bd9Sstevel@tonic-gate 
15707c478bd9Sstevel@tonic-gate 	if (rc == REP_PROTOCOL_SUCCESS)
15717c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_EXISTS);
15727c478bd9Sstevel@tonic-gate 	else if (rc != REP_PROTOCOL_FAIL_NOT_FOUND)
15737c478bd9Sstevel@tonic-gate 		return (rc);
15747c478bd9Sstevel@tonic-gate 
15757c478bd9Sstevel@tonic-gate 	if ((lp->rl_main_id = backend_new_id(tx,
15767c478bd9Sstevel@tonic-gate 	    info[type].obj_id_space)) == 0) {
15777c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_NO_RESOURCES);
15787c478bd9Sstevel@tonic-gate 	}
15797c478bd9Sstevel@tonic-gate 
15807c478bd9Sstevel@tonic-gate 	if ((np = rc_node_alloc()) == NULL)
15817c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_NO_RESOURCES);
15827c478bd9Sstevel@tonic-gate 
15837c478bd9Sstevel@tonic-gate 	if ((rc = (*ip->obj_insert_child)(tx, lp, name)) !=
15847c478bd9Sstevel@tonic-gate 	    REP_PROTOCOL_SUCCESS) {
15857c478bd9Sstevel@tonic-gate 		rc_node_destroy(np);
15867c478bd9Sstevel@tonic-gate 		return (rc);
15877c478bd9Sstevel@tonic-gate 	}
15887c478bd9Sstevel@tonic-gate 
15897c478bd9Sstevel@tonic-gate 	*cpp = np;
15907c478bd9Sstevel@tonic-gate 	return (REP_PROTOCOL_SUCCESS);
15917c478bd9Sstevel@tonic-gate }
15927c478bd9Sstevel@tonic-gate 
15937c478bd9Sstevel@tonic-gate /*
15947c478bd9Sstevel@tonic-gate  * Fails with
15957c478bd9Sstevel@tonic-gate  *   _NOT_APPLICABLE - type is _PROPERTYGRP
15967c478bd9Sstevel@tonic-gate  *   _BAD_REQUEST - cannot create children for this type of node
15977c478bd9Sstevel@tonic-gate  *		    name is invalid
15987c478bd9Sstevel@tonic-gate  *   _TYPE_MISMATCH - object cannot have children of type type
15997c478bd9Sstevel@tonic-gate  *   _NO_RESOURCES - out of memory, or could not allocate new id
16007c478bd9Sstevel@tonic-gate  *   _BACKEND_READONLY
16017c478bd9Sstevel@tonic-gate  *   _BACKEND_ACCESS
16027c478bd9Sstevel@tonic-gate  *   _EXISTS - child already exists
16037c478bd9Sstevel@tonic-gate  */
16047c478bd9Sstevel@tonic-gate int
object_create(rc_node_t * pp,uint32_t type,const char * name,rc_node_t ** cpp)16057c478bd9Sstevel@tonic-gate object_create(rc_node_t *pp, uint32_t type, const char *name, rc_node_t **cpp)
16067c478bd9Sstevel@tonic-gate {
16077c478bd9Sstevel@tonic-gate 	backend_tx_t *tx;
16087c478bd9Sstevel@tonic-gate 	rc_node_t *np = NULL;
16097c478bd9Sstevel@tonic-gate 	child_info_t ci;
16107c478bd9Sstevel@tonic-gate 	int rc;
16117c478bd9Sstevel@tonic-gate 
16127c478bd9Sstevel@tonic-gate 	if ((rc = backend_tx_begin(pp->rn_id.rl_backend, &tx)) !=
16137c478bd9Sstevel@tonic-gate 	    REP_PROTOCOL_SUCCESS) {
16147c478bd9Sstevel@tonic-gate 		return (rc);
16157c478bd9Sstevel@tonic-gate 	}
16167c478bd9Sstevel@tonic-gate 
16177c478bd9Sstevel@tonic-gate 	if ((rc = object_do_create(tx, &ci, pp, type, name, &np)) !=
16187c478bd9Sstevel@tonic-gate 	    REP_PROTOCOL_SUCCESS) {
16197c478bd9Sstevel@tonic-gate 		backend_tx_rollback(tx);
16207c478bd9Sstevel@tonic-gate 		return (rc);
16217c478bd9Sstevel@tonic-gate 	}
16227c478bd9Sstevel@tonic-gate 
16237c478bd9Sstevel@tonic-gate 	rc = backend_tx_commit(tx);
16247c478bd9Sstevel@tonic-gate 	if (rc != REP_PROTOCOL_SUCCESS) {
16257c478bd9Sstevel@tonic-gate 		rc_node_destroy(np);
16267c478bd9Sstevel@tonic-gate 		return (rc);
16277c478bd9Sstevel@tonic-gate 	}
16287c478bd9Sstevel@tonic-gate 
16297c478bd9Sstevel@tonic-gate 	*cpp = rc_node_setup(np, &ci.ci_base_nl, name, ci.ci_parent);
16307c478bd9Sstevel@tonic-gate 
16317c478bd9Sstevel@tonic-gate 	return (REP_PROTOCOL_SUCCESS);
16327c478bd9Sstevel@tonic-gate }
16337c478bd9Sstevel@tonic-gate 
16347c478bd9Sstevel@tonic-gate /*ARGSUSED*/
16357c478bd9Sstevel@tonic-gate int
object_create_pg(rc_node_t * pp,uint32_t type,const char * name,const char * pgtype,uint32_t flags,rc_node_t ** cpp)16367c478bd9Sstevel@tonic-gate object_create_pg(rc_node_t *pp, uint32_t type, const char *name,
16377c478bd9Sstevel@tonic-gate     const char *pgtype, uint32_t flags, rc_node_t **cpp)
16387c478bd9Sstevel@tonic-gate {
16397c478bd9Sstevel@tonic-gate 	uint32_t ptype = pp->rn_id.rl_type;
16407c478bd9Sstevel@tonic-gate 	backend_tx_t *tx_ro, *tx_wr;
16417c478bd9Sstevel@tonic-gate 	backend_query_t *q;
16427c478bd9Sstevel@tonic-gate 	uint32_t id;
16437c478bd9Sstevel@tonic-gate 	uint32_t gen = 0;
16447c478bd9Sstevel@tonic-gate 	rc_node_t *np = NULL;
16457c478bd9Sstevel@tonic-gate 	int rc;
16467c478bd9Sstevel@tonic-gate 	int rc_wr;
16477c478bd9Sstevel@tonic-gate 	int rc_ro;
16487c478bd9Sstevel@tonic-gate 	object_info_t *ip;
16497c478bd9Sstevel@tonic-gate 
16507c478bd9Sstevel@tonic-gate 	int nonpersist = (flags & SCF_PG_FLAG_NONPERSISTENT);
16517c478bd9Sstevel@tonic-gate 
16527c478bd9Sstevel@tonic-gate 	child_info_t ci;
16537c478bd9Sstevel@tonic-gate 	rc_node_lookup_t *lp = &ci.ci_base_nl;
16547c478bd9Sstevel@tonic-gate 
16557c478bd9Sstevel@tonic-gate 	assert(ptype > 0 && ptype < NUM_INFO);
16567c478bd9Sstevel@tonic-gate 
16577c478bd9Sstevel@tonic-gate 	if (ptype != REP_PROTOCOL_ENTITY_SERVICE &&
16587c478bd9Sstevel@tonic-gate 	    ptype != REP_PROTOCOL_ENTITY_INSTANCE)
16597c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_BAD_REQUEST);
16607c478bd9Sstevel@tonic-gate 
16617c478bd9Sstevel@tonic-gate 	ip = &info[ptype];
16627c478bd9Sstevel@tonic-gate 
16637c478bd9Sstevel@tonic-gate 	assert(ip->obj_setup_child_info != NULL &&
16647c478bd9Sstevel@tonic-gate 	    ip->obj_query_child != NULL &&
16657c478bd9Sstevel@tonic-gate 	    ip->obj_insert_pg_child != NULL);
16667c478bd9Sstevel@tonic-gate 
16677c478bd9Sstevel@tonic-gate 	if ((rc = (*ip->obj_setup_child_info)(pp, type, &ci)) !=
16687c478bd9Sstevel@tonic-gate 	    REP_PROTOCOL_SUCCESS)
16697c478bd9Sstevel@tonic-gate 		return (rc);
16707c478bd9Sstevel@tonic-gate 
16717c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
16727c478bd9Sstevel@tonic-gate 	if ((rc = (*ip->obj_query_child)(q, lp, name)) !=
16737c478bd9Sstevel@tonic-gate 	    REP_PROTOCOL_SUCCESS) {
16747c478bd9Sstevel@tonic-gate 		backend_query_free(q);
16757c478bd9Sstevel@tonic-gate 		return (rc);
16767c478bd9Sstevel@tonic-gate 	}
16777c478bd9Sstevel@tonic-gate 
16787c478bd9Sstevel@tonic-gate 	if (!nonpersist) {
16797c478bd9Sstevel@tonic-gate 		lp->rl_backend = BACKEND_TYPE_NORMAL;
16807c478bd9Sstevel@tonic-gate 		rc_wr = backend_tx_begin(BACKEND_TYPE_NORMAL, &tx_wr);
16817c478bd9Sstevel@tonic-gate 		rc_ro = backend_tx_begin_ro(BACKEND_TYPE_NONPERSIST, &tx_ro);
16827c478bd9Sstevel@tonic-gate 	} else {
16837c478bd9Sstevel@tonic-gate 		lp->rl_backend = BACKEND_TYPE_NONPERSIST;
16847c478bd9Sstevel@tonic-gate 		rc_ro = backend_tx_begin_ro(BACKEND_TYPE_NORMAL, &tx_ro);
16857c478bd9Sstevel@tonic-gate 		rc_wr = backend_tx_begin(BACKEND_TYPE_NONPERSIST, &tx_wr);
16867c478bd9Sstevel@tonic-gate 	}
16877c478bd9Sstevel@tonic-gate 
16887c478bd9Sstevel@tonic-gate 	if (rc_wr != REP_PROTOCOL_SUCCESS) {
16897c478bd9Sstevel@tonic-gate 		rc = rc_wr;
16907c478bd9Sstevel@tonic-gate 		goto fail;
16917c478bd9Sstevel@tonic-gate 	}
16927c478bd9Sstevel@tonic-gate 	if (rc_ro != REP_PROTOCOL_SUCCESS &&
16937c478bd9Sstevel@tonic-gate 	    rc_ro != REP_PROTOCOL_FAIL_BACKEND_ACCESS) {
16947c478bd9Sstevel@tonic-gate 		rc = rc_ro;
16957c478bd9Sstevel@tonic-gate 		goto fail;
16967c478bd9Sstevel@tonic-gate 	}
16977c478bd9Sstevel@tonic-gate 
16987c478bd9Sstevel@tonic-gate 	if (tx_ro != NULL) {
16997c478bd9Sstevel@tonic-gate 		rc = backend_tx_run_single_int(tx_ro, q, &id);
17007c478bd9Sstevel@tonic-gate 
17017c478bd9Sstevel@tonic-gate 		if (rc == REP_PROTOCOL_SUCCESS) {
17027c478bd9Sstevel@tonic-gate 			backend_query_free(q);
17037c478bd9Sstevel@tonic-gate 			rc = REP_PROTOCOL_FAIL_EXISTS;
17047c478bd9Sstevel@tonic-gate 			goto fail;
17057c478bd9Sstevel@tonic-gate 		} else if (rc != REP_PROTOCOL_FAIL_NOT_FOUND) {
17067c478bd9Sstevel@tonic-gate 			backend_query_free(q);
17077c478bd9Sstevel@tonic-gate 			goto fail;
17087c478bd9Sstevel@tonic-gate 		}
17097c478bd9Sstevel@tonic-gate 	}
17107c478bd9Sstevel@tonic-gate 
17117c478bd9Sstevel@tonic-gate 	rc = backend_tx_run_single_int(tx_wr, q, &id);
17127c478bd9Sstevel@tonic-gate 	backend_query_free(q);
17137c478bd9Sstevel@tonic-gate 
17147c478bd9Sstevel@tonic-gate 	if (rc == REP_PROTOCOL_SUCCESS) {
17157c478bd9Sstevel@tonic-gate 		rc = REP_PROTOCOL_FAIL_EXISTS;
17167c478bd9Sstevel@tonic-gate 		goto fail;
17177c478bd9Sstevel@tonic-gate 	} else if (rc != REP_PROTOCOL_FAIL_NOT_FOUND) {
17187c478bd9Sstevel@tonic-gate 		goto fail;
17197c478bd9Sstevel@tonic-gate 	}
17207c478bd9Sstevel@tonic-gate 
17217c478bd9Sstevel@tonic-gate 	if (tx_ro != NULL)
17227c478bd9Sstevel@tonic-gate 		backend_tx_end_ro(tx_ro);
17237c478bd9Sstevel@tonic-gate 	tx_ro = NULL;
17247c478bd9Sstevel@tonic-gate 
17257c478bd9Sstevel@tonic-gate 	if ((lp->rl_main_id = backend_new_id(tx_wr,
17267c478bd9Sstevel@tonic-gate 	    info[type].obj_id_space)) == 0) {
17277c478bd9Sstevel@tonic-gate 		rc = REP_PROTOCOL_FAIL_NO_RESOURCES;
17287c478bd9Sstevel@tonic-gate 		goto fail;
17297c478bd9Sstevel@tonic-gate 	}
17307c478bd9Sstevel@tonic-gate 
17317c478bd9Sstevel@tonic-gate 	if ((np = rc_node_alloc()) == NULL) {
17327c478bd9Sstevel@tonic-gate 		rc = REP_PROTOCOL_FAIL_NO_RESOURCES;
17337c478bd9Sstevel@tonic-gate 		goto fail;
17347c478bd9Sstevel@tonic-gate 	}
17357c478bd9Sstevel@tonic-gate 
17367c478bd9Sstevel@tonic-gate 	if ((rc = (*ip->obj_insert_pg_child)(tx_wr, lp, name, pgtype, flags,
17377c478bd9Sstevel@tonic-gate 	    gen)) != REP_PROTOCOL_SUCCESS) {
17387c478bd9Sstevel@tonic-gate 		rc_node_destroy(np);
17397c478bd9Sstevel@tonic-gate 		goto fail;
17407c478bd9Sstevel@tonic-gate 	}
17417c478bd9Sstevel@tonic-gate 
17427c478bd9Sstevel@tonic-gate 	rc = backend_tx_commit(tx_wr);
17437c478bd9Sstevel@tonic-gate 	if (rc != REP_PROTOCOL_SUCCESS) {
17447c478bd9Sstevel@tonic-gate 		rc_node_destroy(np);
17457c478bd9Sstevel@tonic-gate 		return (rc);
17467c478bd9Sstevel@tonic-gate 	}
17477c478bd9Sstevel@tonic-gate 
17487c478bd9Sstevel@tonic-gate 	*cpp = rc_node_setup_pg(np, lp, name, pgtype, flags, gen, ci.ci_parent);
17497c478bd9Sstevel@tonic-gate 
17507c478bd9Sstevel@tonic-gate 	return (REP_PROTOCOL_SUCCESS);
17517c478bd9Sstevel@tonic-gate 
17527c478bd9Sstevel@tonic-gate fail:
17537c478bd9Sstevel@tonic-gate 	if (tx_ro != NULL)
17547c478bd9Sstevel@tonic-gate 		backend_tx_end_ro(tx_ro);
17557c478bd9Sstevel@tonic-gate 	if (tx_wr != NULL)
17567c478bd9Sstevel@tonic-gate 		backend_tx_rollback(tx_wr);
17577c478bd9Sstevel@tonic-gate 	return (rc);
17587c478bd9Sstevel@tonic-gate }
17597c478bd9Sstevel@tonic-gate 
17607c478bd9Sstevel@tonic-gate /*
17617c478bd9Sstevel@tonic-gate  * Given a row of snaplevel number, snaplevel id, service id, service name,
17627c478bd9Sstevel@tonic-gate  * instance id, & instance name, create a rc_snaplevel_t & prepend it onto the
17637c478bd9Sstevel@tonic-gate  * rs_levels list of the rc_snapshot_t passed in as data.
17647c478bd9Sstevel@tonic-gate  * Returns _CONTINUE on success or _ABORT if any allocations fail.
17657c478bd9Sstevel@tonic-gate  */
17667c478bd9Sstevel@tonic-gate /*ARGSUSED*/
17677c478bd9Sstevel@tonic-gate static int
fill_snapshot_cb(void * data,int columns,char ** vals,char ** names)17687c478bd9Sstevel@tonic-gate fill_snapshot_cb(void *data, int columns, char **vals, char **names)
17697c478bd9Sstevel@tonic-gate {
17707c478bd9Sstevel@tonic-gate 	rc_snapshot_t *sp = data;
17717c478bd9Sstevel@tonic-gate 	rc_snaplevel_t *lvl;
17727c478bd9Sstevel@tonic-gate 	char *num = vals[0];
17737c478bd9Sstevel@tonic-gate 	char *id = vals[1];
17747c478bd9Sstevel@tonic-gate 	char *service_id = vals[2];
17757c478bd9Sstevel@tonic-gate 	char *service = vals[3];
17767c478bd9Sstevel@tonic-gate 	char *instance_id = vals[4];
17777c478bd9Sstevel@tonic-gate 	char *instance = vals[5];
17787c478bd9Sstevel@tonic-gate 	assert(columns == 6);
17797c478bd9Sstevel@tonic-gate 
17807c478bd9Sstevel@tonic-gate 	lvl = uu_zalloc(sizeof (*lvl));
17817c478bd9Sstevel@tonic-gate 	if (lvl == NULL)
17827c478bd9Sstevel@tonic-gate 		return (BACKEND_CALLBACK_ABORT);
17837c478bd9Sstevel@tonic-gate 	lvl->rsl_parent = sp;
17847c478bd9Sstevel@tonic-gate 	lvl->rsl_next = sp->rs_levels;
17857c478bd9Sstevel@tonic-gate 	sp->rs_levels = lvl;
17867c478bd9Sstevel@tonic-gate 
17878918dff3Sjwadams 	string_to_id(num, &lvl->rsl_level_num, "snap_level_num");
17888918dff3Sjwadams 	string_to_id(id, &lvl->rsl_level_id, "snap_level_id");
17898918dff3Sjwadams 	string_to_id(service_id, &lvl->rsl_service_id, "snap_level_service_id");
17908918dff3Sjwadams 	if (instance_id != NULL)
17918918dff3Sjwadams 		string_to_id(instance_id, &lvl->rsl_instance_id,
17928918dff3Sjwadams 		    "snap_level_instance_id");
17937c478bd9Sstevel@tonic-gate 
17947c478bd9Sstevel@tonic-gate 	lvl->rsl_scope = (const char *)"localhost";
17957c478bd9Sstevel@tonic-gate 	lvl->rsl_service = strdup(service);
17967c478bd9Sstevel@tonic-gate 	if (lvl->rsl_service == NULL) {
17977c478bd9Sstevel@tonic-gate 		uu_free(lvl);
17987c478bd9Sstevel@tonic-gate 		return (BACKEND_CALLBACK_ABORT);
17997c478bd9Sstevel@tonic-gate 	}
18007c478bd9Sstevel@tonic-gate 	if (instance) {
18017c478bd9Sstevel@tonic-gate 		assert(lvl->rsl_instance_id != 0);
18027c478bd9Sstevel@tonic-gate 		lvl->rsl_instance = strdup(instance);
18037c478bd9Sstevel@tonic-gate 		if (lvl->rsl_instance == NULL) {
18047c478bd9Sstevel@tonic-gate 			free((void *)lvl->rsl_instance);
18057c478bd9Sstevel@tonic-gate 			uu_free(lvl);
18067c478bd9Sstevel@tonic-gate 			return (BACKEND_CALLBACK_ABORT);
18077c478bd9Sstevel@tonic-gate 		}
18087c478bd9Sstevel@tonic-gate 	} else {
18097c478bd9Sstevel@tonic-gate 		assert(lvl->rsl_instance_id == 0);
18107c478bd9Sstevel@tonic-gate 	}
18117c478bd9Sstevel@tonic-gate 
18127c478bd9Sstevel@tonic-gate 	return (BACKEND_CALLBACK_CONTINUE);
18137c478bd9Sstevel@tonic-gate }
18147c478bd9Sstevel@tonic-gate 
18157c478bd9Sstevel@tonic-gate /*
18167c478bd9Sstevel@tonic-gate  * Populate sp's rs_levels list from the snaplevel_tbl table.
18177c478bd9Sstevel@tonic-gate  * Fails with
18187c478bd9Sstevel@tonic-gate  *   _NO_RESOURCES
18197c478bd9Sstevel@tonic-gate  */
18207c478bd9Sstevel@tonic-gate int
object_fill_snapshot(rc_snapshot_t * sp)18217c478bd9Sstevel@tonic-gate object_fill_snapshot(rc_snapshot_t *sp)
18227c478bd9Sstevel@tonic-gate {
18237c478bd9Sstevel@tonic-gate 	backend_query_t *q;
18247c478bd9Sstevel@tonic-gate 	rc_snaplevel_t *sl;
18257c478bd9Sstevel@tonic-gate 	int result;
18267c478bd9Sstevel@tonic-gate 	int i;
18277c478bd9Sstevel@tonic-gate 
18287c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
18297c478bd9Sstevel@tonic-gate 	backend_query_add(q,
18307c478bd9Sstevel@tonic-gate 	    "SELECT snap_level_num, snap_level_id, "
18317c478bd9Sstevel@tonic-gate 	    "    snap_level_service_id, snap_level_service, "
18327c478bd9Sstevel@tonic-gate 	    "    snap_level_instance_id, snap_level_instance "
18337c478bd9Sstevel@tonic-gate 	    "FROM snaplevel_tbl "
18347c478bd9Sstevel@tonic-gate 	    "WHERE snap_id = %d "
18357c478bd9Sstevel@tonic-gate 	    "ORDER BY snap_level_id DESC",
18367c478bd9Sstevel@tonic-gate 	    sp->rs_snap_id);
18377c478bd9Sstevel@tonic-gate 
18387c478bd9Sstevel@tonic-gate 	result = backend_run(BACKEND_TYPE_NORMAL, q, fill_snapshot_cb, sp);
18397c478bd9Sstevel@tonic-gate 	if (result == REP_PROTOCOL_DONE)
18407c478bd9Sstevel@tonic-gate 		result = REP_PROTOCOL_FAIL_NO_RESOURCES;
18417c478bd9Sstevel@tonic-gate 	backend_query_free(q);
18427c478bd9Sstevel@tonic-gate 
18437c478bd9Sstevel@tonic-gate 	if (result == REP_PROTOCOL_SUCCESS) {
18447c478bd9Sstevel@tonic-gate 		i = 0;
18457c478bd9Sstevel@tonic-gate 		for (sl = sp->rs_levels; sl != NULL; sl = sl->rsl_next) {
18467c478bd9Sstevel@tonic-gate 			if (sl->rsl_level_num != ++i) {
18477c478bd9Sstevel@tonic-gate 				backend_panic("snaplevels corrupt; expected "
18487c478bd9Sstevel@tonic-gate 				    "level %d, got %d", i, sl->rsl_level_num);
18497c478bd9Sstevel@tonic-gate 			}
18507c478bd9Sstevel@tonic-gate 		}
18517c478bd9Sstevel@tonic-gate 	}
18527c478bd9Sstevel@tonic-gate 	return (result);
18537c478bd9Sstevel@tonic-gate }
18547c478bd9Sstevel@tonic-gate 
18558918dff3Sjwadams /*
18568918dff3Sjwadams  * This represents a property group in a snapshot.
18578918dff3Sjwadams  */
18588918dff3Sjwadams typedef struct check_snapshot_elem {
18598918dff3Sjwadams 	uint32_t cse_parent;
18608918dff3Sjwadams 	uint32_t cse_pg_id;
18618918dff3Sjwadams 	uint32_t cse_pg_gen;
18628918dff3Sjwadams 	char	cse_seen;
18638918dff3Sjwadams } check_snapshot_elem_t;
18648918dff3Sjwadams 
18658918dff3Sjwadams #define	CSI_MAX_PARENTS		COMPOSITION_DEPTH
18668918dff3Sjwadams typedef struct check_snapshot_info {
18678918dff3Sjwadams 	size_t			csi_count;
18688918dff3Sjwadams 	size_t			csi_array_size;
18698918dff3Sjwadams 	check_snapshot_elem_t	*csi_array;
18708918dff3Sjwadams 	size_t			csi_nparents;
18718918dff3Sjwadams 	uint32_t		csi_parent_ids[CSI_MAX_PARENTS];
18728918dff3Sjwadams } check_snapshot_info_t;
18738918dff3Sjwadams 
18748918dff3Sjwadams /*ARGSUSED*/
18758918dff3Sjwadams static int
check_snapshot_fill_cb(void * data,int columns,char ** vals,char ** names)18768918dff3Sjwadams check_snapshot_fill_cb(void *data, int columns, char **vals, char **names)
18778918dff3Sjwadams {
18788918dff3Sjwadams 	check_snapshot_info_t *csip = data;
18798918dff3Sjwadams 	check_snapshot_elem_t *cur;
18808918dff3Sjwadams 	const char *parent;
18818918dff3Sjwadams 	const char *pg_id;
18828918dff3Sjwadams 	const char *pg_gen_id;
18838918dff3Sjwadams 
18848918dff3Sjwadams 	if (columns == 1) {
18858918dff3Sjwadams 		uint32_t *target;
18868918dff3Sjwadams 
18878918dff3Sjwadams 		if (csip->csi_nparents >= CSI_MAX_PARENTS)
18888918dff3Sjwadams 			backend_panic("snaplevel table has too many elements");
18898918dff3Sjwadams 
18908918dff3Sjwadams 		target = &csip->csi_parent_ids[csip->csi_nparents++];
18918918dff3Sjwadams 		string_to_id(vals[0], target, "snap_level_*_id");
18928918dff3Sjwadams 
18938918dff3Sjwadams 		return (BACKEND_CALLBACK_CONTINUE);
18948918dff3Sjwadams 	}
18958918dff3Sjwadams 
18968918dff3Sjwadams 	assert(columns == 3);
18978918dff3Sjwadams 
18988918dff3Sjwadams 	parent = vals[0];
18998918dff3Sjwadams 	pg_id = vals[1];
19008918dff3Sjwadams 	pg_gen_id = vals[2];
19018918dff3Sjwadams 
19028918dff3Sjwadams 	if (csip->csi_count == csip->csi_array_size) {
19038918dff3Sjwadams 		size_t newsz = (csip->csi_array_size > 0) ?
19048918dff3Sjwadams 		    csip->csi_array_size * 2 : 8;
19058918dff3Sjwadams 		check_snapshot_elem_t *new = uu_zalloc(newsz * sizeof (*new));
19068918dff3Sjwadams 
19078918dff3Sjwadams 		if (new == NULL)
19088918dff3Sjwadams 			return (BACKEND_CALLBACK_ABORT);
19098918dff3Sjwadams 
19108918dff3Sjwadams 		(void) memcpy(new, csip->csi_array,
19118918dff3Sjwadams 		    sizeof (*new) * csip->csi_array_size);
19128918dff3Sjwadams 		uu_free(csip->csi_array);
19138918dff3Sjwadams 		csip->csi_array = new;
19148918dff3Sjwadams 		csip->csi_array_size = newsz;
19158918dff3Sjwadams 	}
19168918dff3Sjwadams 
19178918dff3Sjwadams 	cur = &csip->csi_array[csip->csi_count++];
19188918dff3Sjwadams 
19198918dff3Sjwadams 	string_to_id(parent, &cur->cse_parent, "snap_level_*_id");
19208918dff3Sjwadams 	string_to_id(pg_id, &cur->cse_pg_id, "snaplvl_pg_id");
19218918dff3Sjwadams 	string_to_id(pg_gen_id, &cur->cse_pg_gen, "snaplvl_gen_id");
19228918dff3Sjwadams 	cur->cse_seen = 0;
19238918dff3Sjwadams 
19248918dff3Sjwadams 	return (BACKEND_CALLBACK_CONTINUE);
19258918dff3Sjwadams }
19268918dff3Sjwadams 
19278918dff3Sjwadams static int
check_snapshot_elem_cmp(const void * lhs_arg,const void * rhs_arg)19288918dff3Sjwadams check_snapshot_elem_cmp(const void *lhs_arg, const void *rhs_arg)
19298918dff3Sjwadams {
19308918dff3Sjwadams 	const check_snapshot_elem_t *lhs = lhs_arg;
19318918dff3Sjwadams 	const check_snapshot_elem_t *rhs = rhs_arg;
19328918dff3Sjwadams 
19338918dff3Sjwadams 	if (lhs->cse_parent < rhs->cse_parent)
19348918dff3Sjwadams 		return (-1);
19358918dff3Sjwadams 	if (lhs->cse_parent > rhs->cse_parent)
19368918dff3Sjwadams 		return (1);
19378918dff3Sjwadams 
19388918dff3Sjwadams 	if (lhs->cse_pg_id < rhs->cse_pg_id)
19398918dff3Sjwadams 		return (-1);
19408918dff3Sjwadams 	if (lhs->cse_pg_id > rhs->cse_pg_id)
19418918dff3Sjwadams 		return (1);
19428918dff3Sjwadams 
19438918dff3Sjwadams 	if (lhs->cse_pg_gen < rhs->cse_pg_gen)
19448918dff3Sjwadams 		return (-1);
19458918dff3Sjwadams 	if (lhs->cse_pg_gen > rhs->cse_pg_gen)
19468918dff3Sjwadams 		return (1);
19478918dff3Sjwadams 
19488918dff3Sjwadams 	return (0);
19498918dff3Sjwadams }
19508918dff3Sjwadams 
19518918dff3Sjwadams /*ARGSUSED*/
19528918dff3Sjwadams static int
check_snapshot_check_cb(void * data,int columns,char ** vals,char ** names)19538918dff3Sjwadams check_snapshot_check_cb(void *data, int columns, char **vals, char **names)
19548918dff3Sjwadams {
19558918dff3Sjwadams 	check_snapshot_info_t *csip = data;
19568918dff3Sjwadams 	check_snapshot_elem_t elem;
19578918dff3Sjwadams 	check_snapshot_elem_t *cur;
19588918dff3Sjwadams 
19598918dff3Sjwadams 	const char *parent = vals[0];
19608918dff3Sjwadams 	const char *pg_id = vals[1];
19618918dff3Sjwadams 	const char *pg_gen_id = vals[2];
19628918dff3Sjwadams 
19638918dff3Sjwadams 	assert(columns == 3);
19648918dff3Sjwadams 
19658918dff3Sjwadams 	string_to_id(parent, &elem.cse_parent, "snap_level_*_id");
19668918dff3Sjwadams 	string_to_id(pg_id, &elem.cse_pg_id, "snaplvl_pg_id");
19678918dff3Sjwadams 	string_to_id(pg_gen_id, &elem.cse_pg_gen, "snaplvl_gen_id");
19688918dff3Sjwadams 
19698918dff3Sjwadams 	if ((cur = bsearch(&elem, csip->csi_array, csip->csi_count,
19708918dff3Sjwadams 	    sizeof (*csip->csi_array), check_snapshot_elem_cmp)) == NULL)
19718918dff3Sjwadams 		return (BACKEND_CALLBACK_ABORT);
19728918dff3Sjwadams 
19738918dff3Sjwadams 	if (cur->cse_seen)
19748918dff3Sjwadams 		backend_panic("duplicate property group reported");
19758918dff3Sjwadams 	cur->cse_seen = 1;
19768918dff3Sjwadams 	return (BACKEND_CALLBACK_CONTINUE);
19778918dff3Sjwadams }
19788918dff3Sjwadams 
19798918dff3Sjwadams /*
19808918dff3Sjwadams  * Check that a snapshot matches up with the latest in the repository.
19818918dff3Sjwadams  * Returns:
19828918dff3Sjwadams  *	REP_PROTOCOL_SUCCESS		if it is up-to-date,
19838918dff3Sjwadams  *	REP_PROTOCOL_DONE		if it is out-of-date, or
19848918dff3Sjwadams  *	REP_PROTOCOL_FAIL_NO_RESOURCES	if we ran out of memory.
19858918dff3Sjwadams  */
19868918dff3Sjwadams static int
object_check_snapshot(uint32_t snap_id)19878918dff3Sjwadams object_check_snapshot(uint32_t snap_id)
19888918dff3Sjwadams {
19898918dff3Sjwadams 	check_snapshot_info_t csi;
19908918dff3Sjwadams 	backend_query_t *q;
19918918dff3Sjwadams 	int result;
19928918dff3Sjwadams 	size_t idx;
19938918dff3Sjwadams 
19948918dff3Sjwadams 	/* if the snapshot has never been taken, it must be out of date. */
19958918dff3Sjwadams 	if (snap_id == 0)
19968918dff3Sjwadams 		return (REP_PROTOCOL_DONE);
19978918dff3Sjwadams 
19988918dff3Sjwadams 	(void) memset(&csi, '\0', sizeof (csi));
19998918dff3Sjwadams 
20008918dff3Sjwadams 	q = backend_query_alloc();
20018918dff3Sjwadams 	backend_query_add(q,
20028918dff3Sjwadams 	    "SELECT\n"
20038918dff3Sjwadams 	    "    CASE snap_level_instance_id\n"
20048918dff3Sjwadams 	    "        WHEN 0 THEN snap_level_service_id\n"
20058918dff3Sjwadams 	    "        ELSE snap_level_instance_id\n"
20068918dff3Sjwadams 	    "    END\n"
20078918dff3Sjwadams 	    "FROM snaplevel_tbl\n"
20088918dff3Sjwadams 	    "WHERE snap_id = %d;\n"
20098918dff3Sjwadams 	    "\n"
20108918dff3Sjwadams 	    "SELECT\n"
20118918dff3Sjwadams 	    "    CASE snap_level_instance_id\n"
20128918dff3Sjwadams 	    "        WHEN 0 THEN snap_level_service_id\n"
20138918dff3Sjwadams 	    "        ELSE snap_level_instance_id\n"
20148918dff3Sjwadams 	    "    END,\n"
20158918dff3Sjwadams 	    "    snaplvl_pg_id,\n"
20168918dff3Sjwadams 	    "    snaplvl_gen_id\n"
20178918dff3Sjwadams 	    "FROM snaplevel_tbl, snaplevel_lnk_tbl\n"
20188918dff3Sjwadams 	    "WHERE\n"
20198918dff3Sjwadams 	    "    (snaplvl_level_id = snap_level_id AND\n"
20208918dff3Sjwadams 	    "    snap_id = %d);",
20218918dff3Sjwadams 	    snap_id, snap_id);
20228918dff3Sjwadams 
20238918dff3Sjwadams 	result = backend_run(BACKEND_TYPE_NORMAL, q, check_snapshot_fill_cb,
20248918dff3Sjwadams 	    &csi);
20258918dff3Sjwadams 	if (result == REP_PROTOCOL_DONE)
20268918dff3Sjwadams 		result = REP_PROTOCOL_FAIL_NO_RESOURCES;
20278918dff3Sjwadams 	backend_query_free(q);
20288918dff3Sjwadams 
20298918dff3Sjwadams 	if (result != REP_PROTOCOL_SUCCESS)
20308918dff3Sjwadams 		goto fail;
20318918dff3Sjwadams 
20328918dff3Sjwadams 	if (csi.csi_count > 0) {
20338918dff3Sjwadams 		qsort(csi.csi_array, csi.csi_count, sizeof (*csi.csi_array),
20348918dff3Sjwadams 		    check_snapshot_elem_cmp);
20358918dff3Sjwadams 	}
20368918dff3Sjwadams 
20378918dff3Sjwadams #if COMPOSITION_DEPTH == 2
20388918dff3Sjwadams 	if (csi.csi_nparents != COMPOSITION_DEPTH) {
20398918dff3Sjwadams 		result = REP_PROTOCOL_DONE;
20408918dff3Sjwadams 		goto fail;
20418918dff3Sjwadams 	}
20428918dff3Sjwadams 
20438918dff3Sjwadams 	q = backend_query_alloc();
20448918dff3Sjwadams 	backend_query_add(q,
20458918dff3Sjwadams 	    "SELECT "
20468918dff3Sjwadams 	    "    pg_parent_id, pg_id, pg_gen_id "
20478918dff3Sjwadams 	    "FROM "
20488918dff3Sjwadams 	    "    pg_tbl "
20498918dff3Sjwadams 	    "WHERE (pg_parent_id = %d OR pg_parent_id = %d)",
20508918dff3Sjwadams 	    csi.csi_parent_ids[0], csi.csi_parent_ids[1]);
20518918dff3Sjwadams 
20528918dff3Sjwadams 	result = backend_run(BACKEND_TYPE_NORMAL, q, check_snapshot_check_cb,
20538918dff3Sjwadams 	    &csi);
20548918dff3Sjwadams #else
20558918dff3Sjwadams #error This code must be updated
20568918dff3Sjwadams #endif
20578918dff3Sjwadams 	/*
20588918dff3Sjwadams 	 * To succeed, the callback must not have aborted, and we must have
20598918dff3Sjwadams 	 * found all of the items.
20608918dff3Sjwadams 	 */
20618918dff3Sjwadams 	if (result == REP_PROTOCOL_SUCCESS) {
20628918dff3Sjwadams 		for (idx = 0; idx < csi.csi_count; idx++) {
20638918dff3Sjwadams 			if (csi.csi_array[idx].cse_seen == 0) {
20648918dff3Sjwadams 				result = REP_PROTOCOL_DONE;
20658918dff3Sjwadams 				goto fail;
20668918dff3Sjwadams 			}
20678918dff3Sjwadams 		}
20688918dff3Sjwadams 	}
20698918dff3Sjwadams 
20708918dff3Sjwadams fail:
20718918dff3Sjwadams 	uu_free(csi.csi_array);
20728918dff3Sjwadams 	return (result);
20738918dff3Sjwadams }
20748918dff3Sjwadams 
20757c478bd9Sstevel@tonic-gate /*ARGSUSED*/
20767c478bd9Sstevel@tonic-gate static int
object_copy_string(void * data_arg,int columns,char ** vals,char ** names)20777c478bd9Sstevel@tonic-gate object_copy_string(void *data_arg, int columns, char **vals, char **names)
20787c478bd9Sstevel@tonic-gate {
20797c478bd9Sstevel@tonic-gate 	char **data = data_arg;
20807c478bd9Sstevel@tonic-gate 
20817c478bd9Sstevel@tonic-gate 	assert(columns == 1);
20827c478bd9Sstevel@tonic-gate 
20837c478bd9Sstevel@tonic-gate 	if (*data != NULL)
20847c478bd9Sstevel@tonic-gate 		free(*data);
20857c478bd9Sstevel@tonic-gate 	*data = NULL;
20867c478bd9Sstevel@tonic-gate 
20877c478bd9Sstevel@tonic-gate 	if (vals[0] != NULL) {
20887c478bd9Sstevel@tonic-gate 		if ((*data = strdup(vals[0])) == NULL)
20897c478bd9Sstevel@tonic-gate 			return (BACKEND_CALLBACK_ABORT);
20907c478bd9Sstevel@tonic-gate 	}
20917c478bd9Sstevel@tonic-gate 
20927c478bd9Sstevel@tonic-gate 	return (BACKEND_CALLBACK_CONTINUE);
20937c478bd9Sstevel@tonic-gate }
20947c478bd9Sstevel@tonic-gate 
20957c478bd9Sstevel@tonic-gate struct snaplevel_add_info {
20967c478bd9Sstevel@tonic-gate 	backend_query_t *sai_q;
20977c478bd9Sstevel@tonic-gate 	uint32_t	sai_level_id;
20987c478bd9Sstevel@tonic-gate 	int		sai_used;		/* sai_q has been used */
20997c478bd9Sstevel@tonic-gate };
21007c478bd9Sstevel@tonic-gate 
21017c478bd9Sstevel@tonic-gate /*ARGSUSED*/
21027c478bd9Sstevel@tonic-gate static int
object_snaplevel_process_pg(void * data_arg,int columns,char ** vals,char ** names)21037c478bd9Sstevel@tonic-gate object_snaplevel_process_pg(void *data_arg, int columns, char **vals,
21047c478bd9Sstevel@tonic-gate     char **names)
21057c478bd9Sstevel@tonic-gate {
21067c478bd9Sstevel@tonic-gate 	struct snaplevel_add_info *data = data_arg;
21077c478bd9Sstevel@tonic-gate 
21087c478bd9Sstevel@tonic-gate 	assert(columns == 5);
21097c478bd9Sstevel@tonic-gate 
21107c478bd9Sstevel@tonic-gate 	backend_query_add(data->sai_q,
21117c478bd9Sstevel@tonic-gate 	    "INSERT INTO snaplevel_lnk_tbl "
21127c478bd9Sstevel@tonic-gate 	    "    (snaplvl_level_id, snaplvl_pg_id, snaplvl_pg_name, "
21137c478bd9Sstevel@tonic-gate 	    "    snaplvl_pg_type, snaplvl_pg_flags, snaplvl_gen_id)"
21147c478bd9Sstevel@tonic-gate 	    "VALUES (%d, %s, '%q', '%q', %s, %s);",
21157c478bd9Sstevel@tonic-gate 	    data->sai_level_id, vals[0], vals[1], vals[2], vals[3], vals[4]);
21167c478bd9Sstevel@tonic-gate 
21177c478bd9Sstevel@tonic-gate 	data->sai_used = 1;
21187c478bd9Sstevel@tonic-gate 
21197c478bd9Sstevel@tonic-gate 	return (BACKEND_CALLBACK_CONTINUE);
21207c478bd9Sstevel@tonic-gate }
21217c478bd9Sstevel@tonic-gate 
21227c478bd9Sstevel@tonic-gate /*ARGSUSED*/
21237c478bd9Sstevel@tonic-gate static int
object_snapshot_add_level(backend_tx_t * tx,uint32_t snap_id,uint32_t snap_level_num,uint32_t svc_id,const char * svc_name,uint32_t inst_id,const char * inst_name)21247c478bd9Sstevel@tonic-gate object_snapshot_add_level(backend_tx_t *tx, uint32_t snap_id,
21257c478bd9Sstevel@tonic-gate     uint32_t snap_level_num, uint32_t svc_id, const char *svc_name,
21267c478bd9Sstevel@tonic-gate     uint32_t inst_id, const char *inst_name)
21277c478bd9Sstevel@tonic-gate {
21287c478bd9Sstevel@tonic-gate 	struct snaplevel_add_info data;
21297c478bd9Sstevel@tonic-gate 	backend_query_t *q;
21307c478bd9Sstevel@tonic-gate 	int result;
21317c478bd9Sstevel@tonic-gate 
21327c478bd9Sstevel@tonic-gate 	assert((snap_level_num == 1 && inst_name != NULL) ||
21337c478bd9Sstevel@tonic-gate 	    snap_level_num == 2 && inst_name == NULL);
21347c478bd9Sstevel@tonic-gate 
21357c478bd9Sstevel@tonic-gate 	data.sai_level_id = backend_new_id(tx, BACKEND_ID_SNAPLEVEL);
21367c478bd9Sstevel@tonic-gate 	if (data.sai_level_id == 0) {
21377c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_NO_RESOURCES);
21387c478bd9Sstevel@tonic-gate 	}
21397c478bd9Sstevel@tonic-gate 
21407c478bd9Sstevel@tonic-gate 	result = backend_tx_run_update(tx,
21417c478bd9Sstevel@tonic-gate 	    "INSERT INTO snaplevel_tbl "
21427c478bd9Sstevel@tonic-gate 	    "    (snap_id, snap_level_num, snap_level_id, "
21437c478bd9Sstevel@tonic-gate 	    "    snap_level_service_id, snap_level_service, "
21447c478bd9Sstevel@tonic-gate 	    "    snap_level_instance_id, snap_level_instance) "
21457c478bd9Sstevel@tonic-gate 	    "VALUES (%d, %d, %d, %d, %Q, %d, %Q);",
21467c478bd9Sstevel@tonic-gate 	    snap_id, snap_level_num, data.sai_level_id, svc_id, svc_name,
21477c478bd9Sstevel@tonic-gate 	    inst_id, inst_name);
21487c478bd9Sstevel@tonic-gate 
21497c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
21507c478bd9Sstevel@tonic-gate 	backend_query_add(q,
21517c478bd9Sstevel@tonic-gate 	    "SELECT pg_id, pg_name, pg_type, pg_flags, pg_gen_id FROM pg_tbl "
21527c478bd9Sstevel@tonic-gate 	    "WHERE (pg_parent_id = %d);",
21537c478bd9Sstevel@tonic-gate 	    (inst_name != NULL)? inst_id : svc_id);
21547c478bd9Sstevel@tonic-gate 
21557c478bd9Sstevel@tonic-gate 	data.sai_q = backend_query_alloc();
21567c478bd9Sstevel@tonic-gate 	data.sai_used = 0;
21577c478bd9Sstevel@tonic-gate 	result = backend_tx_run(tx, q, object_snaplevel_process_pg,
21587c478bd9Sstevel@tonic-gate 	    &data);
21597c478bd9Sstevel@tonic-gate 	backend_query_free(q);
21607c478bd9Sstevel@tonic-gate 
21617c478bd9Sstevel@tonic-gate 	if (result == REP_PROTOCOL_SUCCESS && data.sai_used != 0)
21627c478bd9Sstevel@tonic-gate 		result = backend_tx_run(tx, data.sai_q, NULL, NULL);
21637c478bd9Sstevel@tonic-gate 	backend_query_free(data.sai_q);
21647c478bd9Sstevel@tonic-gate 
21657c478bd9Sstevel@tonic-gate 	return (result);
21667c478bd9Sstevel@tonic-gate }
21677c478bd9Sstevel@tonic-gate 
21687c478bd9Sstevel@tonic-gate /*
21697c478bd9Sstevel@tonic-gate  * Fails with:
21707c478bd9Sstevel@tonic-gate  *	_NO_RESOURCES - no new id or out of disk space
21717c478bd9Sstevel@tonic-gate  *	_BACKEND_READONLY - persistent backend is read-only
21727c478bd9Sstevel@tonic-gate  */
21737c478bd9Sstevel@tonic-gate static int
object_snapshot_do_take(uint32_t instid,const char * inst_name,uint32_t svcid,const char * svc_name,backend_tx_t ** tx_out,uint32_t * snapid_out)21747c478bd9Sstevel@tonic-gate object_snapshot_do_take(uint32_t instid, const char *inst_name,
21757c478bd9Sstevel@tonic-gate     uint32_t svcid, const char *svc_name,
21767c478bd9Sstevel@tonic-gate     backend_tx_t **tx_out, uint32_t *snapid_out)
21777c478bd9Sstevel@tonic-gate {
21787c478bd9Sstevel@tonic-gate 	backend_tx_t *tx;
21797c478bd9Sstevel@tonic-gate 	backend_query_t *q;
21807c478bd9Sstevel@tonic-gate 	int result;
21817c478bd9Sstevel@tonic-gate 
21827c478bd9Sstevel@tonic-gate 	char *svc_name_alloc = NULL;
21837c478bd9Sstevel@tonic-gate 	char *inst_name_alloc = NULL;
21847c478bd9Sstevel@tonic-gate 	uint32_t snapid;
21857c478bd9Sstevel@tonic-gate 
21867c478bd9Sstevel@tonic-gate 	result = backend_tx_begin(BACKEND_TYPE_NORMAL, &tx);
21877c478bd9Sstevel@tonic-gate 	if (result != REP_PROTOCOL_SUCCESS)
21887c478bd9Sstevel@tonic-gate 		return (result);
21897c478bd9Sstevel@tonic-gate 
21907c478bd9Sstevel@tonic-gate 	snapid = backend_new_id(tx, BACKEND_ID_SNAPSHOT);
21917c478bd9Sstevel@tonic-gate 	if (snapid == 0) {
21927c478bd9Sstevel@tonic-gate 		result = REP_PROTOCOL_FAIL_NO_RESOURCES;
21937c478bd9Sstevel@tonic-gate 		goto fail;
21947c478bd9Sstevel@tonic-gate 	}
21957c478bd9Sstevel@tonic-gate 
21967c478bd9Sstevel@tonic-gate 	if (svc_name == NULL) {
21977c478bd9Sstevel@tonic-gate 		q = backend_query_alloc();
21987c478bd9Sstevel@tonic-gate 		backend_query_add(q,
21997c478bd9Sstevel@tonic-gate 		    "SELECT svc_name FROM service_tbl "
22007c478bd9Sstevel@tonic-gate 		    "WHERE (svc_id = %d)", svcid);
22017c478bd9Sstevel@tonic-gate 		result = backend_tx_run(tx, q, object_copy_string,
22027c478bd9Sstevel@tonic-gate 		    &svc_name_alloc);
22037c478bd9Sstevel@tonic-gate 		backend_query_free(q);
22047c478bd9Sstevel@tonic-gate 
22057c478bd9Sstevel@tonic-gate 		svc_name = svc_name_alloc;
22067c478bd9Sstevel@tonic-gate 
22077c478bd9Sstevel@tonic-gate 		if (result == REP_PROTOCOL_DONE) {
22087c478bd9Sstevel@tonic-gate 			result = REP_PROTOCOL_FAIL_NO_RESOURCES;
22097c478bd9Sstevel@tonic-gate 			goto fail;
22107c478bd9Sstevel@tonic-gate 		}
22117c478bd9Sstevel@tonic-gate 		if (result == REP_PROTOCOL_SUCCESS && svc_name == NULL)
22127c478bd9Sstevel@tonic-gate 			backend_panic("unable to find name for svc id %d\n",
22137c478bd9Sstevel@tonic-gate 			    svcid);
22147c478bd9Sstevel@tonic-gate 
22157c478bd9Sstevel@tonic-gate 		if (result != REP_PROTOCOL_SUCCESS)
22167c478bd9Sstevel@tonic-gate 			goto fail;
22177c478bd9Sstevel@tonic-gate 	}
22187c478bd9Sstevel@tonic-gate 
22197c478bd9Sstevel@tonic-gate 	if (inst_name == NULL) {
22207c478bd9Sstevel@tonic-gate 		q = backend_query_alloc();
22217c478bd9Sstevel@tonic-gate 		backend_query_add(q,
22227c478bd9Sstevel@tonic-gate 		    "SELECT instance_name FROM instance_tbl "
22237c478bd9Sstevel@tonic-gate 		    "WHERE (instance_id = %d)", instid);
22247c478bd9Sstevel@tonic-gate 		result = backend_tx_run(tx, q, object_copy_string,
22257c478bd9Sstevel@tonic-gate 		    &inst_name_alloc);
22267c478bd9Sstevel@tonic-gate 		backend_query_free(q);
22277c478bd9Sstevel@tonic-gate 
22287c478bd9Sstevel@tonic-gate 		inst_name = inst_name_alloc;
22297c478bd9Sstevel@tonic-gate 
22307c478bd9Sstevel@tonic-gate 		if (result == REP_PROTOCOL_DONE) {
22317c478bd9Sstevel@tonic-gate 			result = REP_PROTOCOL_FAIL_NO_RESOURCES;
22327c478bd9Sstevel@tonic-gate 			goto fail;
22337c478bd9Sstevel@tonic-gate 		}
22347c478bd9Sstevel@tonic-gate 
22357c478bd9Sstevel@tonic-gate 		if (result == REP_PROTOCOL_SUCCESS && inst_name == NULL)
22367c478bd9Sstevel@tonic-gate 			backend_panic(
22377c478bd9Sstevel@tonic-gate 			    "unable to find name for instance id %d\n", instid);
22387c478bd9Sstevel@tonic-gate 
22397c478bd9Sstevel@tonic-gate 		if (result != REP_PROTOCOL_SUCCESS)
22407c478bd9Sstevel@tonic-gate 			goto fail;
22417c478bd9Sstevel@tonic-gate 	}
22427c478bd9Sstevel@tonic-gate 
22437c478bd9Sstevel@tonic-gate 	result = object_snapshot_add_level(tx, snapid, 1,
22447c478bd9Sstevel@tonic-gate 	    svcid, svc_name, instid, inst_name);
22457c478bd9Sstevel@tonic-gate 
22467c478bd9Sstevel@tonic-gate 	if (result != REP_PROTOCOL_SUCCESS)
22477c478bd9Sstevel@tonic-gate 		goto fail;
22487c478bd9Sstevel@tonic-gate 
22497c478bd9Sstevel@tonic-gate 	result = object_snapshot_add_level(tx, snapid, 2,
22507c478bd9Sstevel@tonic-gate 	    svcid, svc_name, 0, NULL);
22517c478bd9Sstevel@tonic-gate 
22527c478bd9Sstevel@tonic-gate 	if (result != REP_PROTOCOL_SUCCESS)
22537c478bd9Sstevel@tonic-gate 		goto fail;
22547c478bd9Sstevel@tonic-gate 
22557c478bd9Sstevel@tonic-gate 	*snapid_out = snapid;
22567c478bd9Sstevel@tonic-gate 	*tx_out = tx;
22577c478bd9Sstevel@tonic-gate 
22587c478bd9Sstevel@tonic-gate 	free(svc_name_alloc);
22597c478bd9Sstevel@tonic-gate 	free(inst_name_alloc);
22607c478bd9Sstevel@tonic-gate 
22617c478bd9Sstevel@tonic-gate 	return (REP_PROTOCOL_SUCCESS);
22627c478bd9Sstevel@tonic-gate 
22637c478bd9Sstevel@tonic-gate fail:
22647c478bd9Sstevel@tonic-gate 	backend_tx_rollback(tx);
22657c478bd9Sstevel@tonic-gate 	free(svc_name_alloc);
22667c478bd9Sstevel@tonic-gate 	free(inst_name_alloc);
22677c478bd9Sstevel@tonic-gate 	return (result);
22687c478bd9Sstevel@tonic-gate }
22697c478bd9Sstevel@tonic-gate 
22707c478bd9Sstevel@tonic-gate /*
22717c478bd9Sstevel@tonic-gate  * Fails with:
22727c478bd9Sstevel@tonic-gate  *	_TYPE_MISMATCH - pp is not an instance
22737c478bd9Sstevel@tonic-gate  *	_NO_RESOURCES - no new id or out of disk space
22747c478bd9Sstevel@tonic-gate  *	_BACKEND_READONLY - persistent backend is read-only
22757c478bd9Sstevel@tonic-gate  */
22767c478bd9Sstevel@tonic-gate int
object_snapshot_take_new(rc_node_t * pp,const char * svc_name,const char * inst_name,const char * name,rc_node_t ** outp)22777c478bd9Sstevel@tonic-gate object_snapshot_take_new(rc_node_t *pp,
22787c478bd9Sstevel@tonic-gate     const char *svc_name, const char *inst_name,
22797c478bd9Sstevel@tonic-gate     const char *name, rc_node_t **outp)
22807c478bd9Sstevel@tonic-gate {
22817c478bd9Sstevel@tonic-gate 	rc_node_lookup_t *insti = &pp->rn_id;
22827c478bd9Sstevel@tonic-gate 
22837c478bd9Sstevel@tonic-gate 	uint32_t instid = insti->rl_main_id;
22847c478bd9Sstevel@tonic-gate 	uint32_t svcid = insti->rl_ids[ID_SERVICE];
22857c478bd9Sstevel@tonic-gate 	uint32_t snapid = 0;
22867c478bd9Sstevel@tonic-gate 	backend_tx_t *tx = NULL;
22877c478bd9Sstevel@tonic-gate 	child_info_t ci;
22887c478bd9Sstevel@tonic-gate 	rc_node_t *np;
22897c478bd9Sstevel@tonic-gate 	int result;
22907c478bd9Sstevel@tonic-gate 
22917c478bd9Sstevel@tonic-gate 	if (insti->rl_type != REP_PROTOCOL_ENTITY_INSTANCE)
22927c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
22937c478bd9Sstevel@tonic-gate 
22947c478bd9Sstevel@tonic-gate 	result = object_snapshot_do_take(instid, inst_name, svcid, svc_name,
22957c478bd9Sstevel@tonic-gate 	    &tx, &snapid);
22967c478bd9Sstevel@tonic-gate 	if (result != REP_PROTOCOL_SUCCESS)
22977c478bd9Sstevel@tonic-gate 		return (result);
22987c478bd9Sstevel@tonic-gate 
22997c478bd9Sstevel@tonic-gate 	if ((result = object_do_create(tx, &ci, pp,
23007c478bd9Sstevel@tonic-gate 	    REP_PROTOCOL_ENTITY_SNAPSHOT, name, &np)) != REP_PROTOCOL_SUCCESS) {
23017c478bd9Sstevel@tonic-gate 		backend_tx_rollback(tx);
23027c478bd9Sstevel@tonic-gate 		return (result);
23037c478bd9Sstevel@tonic-gate 	}
23047c478bd9Sstevel@tonic-gate 
23057c478bd9Sstevel@tonic-gate 	/*
23067c478bd9Sstevel@tonic-gate 	 * link the new object to the new snapshot.
23077c478bd9Sstevel@tonic-gate 	 */
23087c478bd9Sstevel@tonic-gate 	np->rn_snapshot_id = snapid;
23097c478bd9Sstevel@tonic-gate 
23107c478bd9Sstevel@tonic-gate 	result = backend_tx_run_update(tx,
23117c478bd9Sstevel@tonic-gate 	    "UPDATE snapshot_lnk_tbl SET lnk_snap_id = %d WHERE lnk_id = %d;",
23127c478bd9Sstevel@tonic-gate 	    snapid, ci.ci_base_nl.rl_main_id);
23137c478bd9Sstevel@tonic-gate 	if (result != REP_PROTOCOL_SUCCESS) {
23147c478bd9Sstevel@tonic-gate 		backend_tx_rollback(tx);
23157c478bd9Sstevel@tonic-gate 		rc_node_destroy(np);
23167c478bd9Sstevel@tonic-gate 		return (result);
23177c478bd9Sstevel@tonic-gate 	}
23187c478bd9Sstevel@tonic-gate 	result = backend_tx_commit(tx);
23197c478bd9Sstevel@tonic-gate 	if (result != REP_PROTOCOL_SUCCESS) {
23207c478bd9Sstevel@tonic-gate 		rc_node_destroy(np);
23217c478bd9Sstevel@tonic-gate 		return (result);
23227c478bd9Sstevel@tonic-gate 	}
23237c478bd9Sstevel@tonic-gate 
23247c478bd9Sstevel@tonic-gate 	*outp = rc_node_setup(np, &ci.ci_base_nl, name, ci.ci_parent);
23257c478bd9Sstevel@tonic-gate 	return (REP_PROTOCOL_SUCCESS);
23267c478bd9Sstevel@tonic-gate }
23277c478bd9Sstevel@tonic-gate 
23287c478bd9Sstevel@tonic-gate /*
23297c478bd9Sstevel@tonic-gate  * Fails with:
23307c478bd9Sstevel@tonic-gate  *	_TYPE_MISMATCH - pp is not an instance
23317c478bd9Sstevel@tonic-gate  *	_NO_RESOURCES - no new id or out of disk space
23327c478bd9Sstevel@tonic-gate  *	_BACKEND_READONLY - persistent backend is read-only
23337c478bd9Sstevel@tonic-gate  */
23347c478bd9Sstevel@tonic-gate int
object_snapshot_attach(rc_node_lookup_t * snapi,uint32_t * snapid_ptr,int takesnap)23357c478bd9Sstevel@tonic-gate object_snapshot_attach(rc_node_lookup_t *snapi, uint32_t *snapid_ptr,
23367c478bd9Sstevel@tonic-gate     int takesnap)
23377c478bd9Sstevel@tonic-gate {
23387c478bd9Sstevel@tonic-gate 	uint32_t svcid = snapi->rl_ids[ID_SERVICE];
23397c478bd9Sstevel@tonic-gate 	uint32_t instid = snapi->rl_ids[ID_INSTANCE];
23407c478bd9Sstevel@tonic-gate 	uint32_t snapid = *snapid_ptr;
23417c478bd9Sstevel@tonic-gate 	uint32_t oldsnapid = 0;
23427c478bd9Sstevel@tonic-gate 	backend_tx_t *tx = NULL;
23437c478bd9Sstevel@tonic-gate 	backend_query_t *q;
23447c478bd9Sstevel@tonic-gate 	int result;
23457c478bd9Sstevel@tonic-gate 
23467c478bd9Sstevel@tonic-gate 	delete_info_t dip;
23477c478bd9Sstevel@tonic-gate 	delete_ent_t de;
23487c478bd9Sstevel@tonic-gate 
23497c478bd9Sstevel@tonic-gate 	if (snapi->rl_type != REP_PROTOCOL_ENTITY_SNAPSHOT)
23507c478bd9Sstevel@tonic-gate 		return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
23517c478bd9Sstevel@tonic-gate 
23527c478bd9Sstevel@tonic-gate 	if (takesnap) {
23538918dff3Sjwadams 		/* first, check that we're actually out of date */
23548918dff3Sjwadams 		if (object_check_snapshot(snapid) == REP_PROTOCOL_SUCCESS)
23558918dff3Sjwadams 			return (REP_PROTOCOL_SUCCESS);
23568918dff3Sjwadams 
23577c478bd9Sstevel@tonic-gate 		result = object_snapshot_do_take(instid, NULL,
23587c478bd9Sstevel@tonic-gate 		    svcid, NULL, &tx, &snapid);
23597c478bd9Sstevel@tonic-gate 		if (result != REP_PROTOCOL_SUCCESS)
23607c478bd9Sstevel@tonic-gate 			return (result);
23617c478bd9Sstevel@tonic-gate 	} else {
23627c478bd9Sstevel@tonic-gate 		result = backend_tx_begin(BACKEND_TYPE_NORMAL, &tx);
23637c478bd9Sstevel@tonic-gate 		if (result != REP_PROTOCOL_SUCCESS)
23647c478bd9Sstevel@tonic-gate 			return (result);
23657c478bd9Sstevel@tonic-gate 	}
23667c478bd9Sstevel@tonic-gate 
23677c478bd9Sstevel@tonic-gate 	q = backend_query_alloc();
23687c478bd9Sstevel@tonic-gate 	backend_query_add(q,
23697c478bd9Sstevel@tonic-gate 	    "SELECT lnk_snap_id FROM snapshot_lnk_tbl WHERE lnk_id = %d; "
23707c478bd9Sstevel@tonic-gate 	    "UPDATE snapshot_lnk_tbl SET lnk_snap_id = %d WHERE lnk_id = %d;",
23717c478bd9Sstevel@tonic-gate 	    snapi->rl_main_id, snapid, snapi->rl_main_id);
23727c478bd9Sstevel@tonic-gate 	result = backend_tx_run_single_int(tx, q, &oldsnapid);
23737c478bd9Sstevel@tonic-gate 	backend_query_free(q);
23747c478bd9Sstevel@tonic-gate 
23757c478bd9Sstevel@tonic-gate 	if (result == REP_PROTOCOL_FAIL_NOT_FOUND) {
23767c478bd9Sstevel@tonic-gate 		backend_tx_rollback(tx);
23777c478bd9Sstevel@tonic-gate 		backend_panic("unable to find snapshot id %d",
23787c478bd9Sstevel@tonic-gate 		    snapi->rl_main_id);
23797c478bd9Sstevel@tonic-gate 	}
23807c478bd9Sstevel@tonic-gate 	if (result != REP_PROTOCOL_SUCCESS)
23817c478bd9Sstevel@tonic-gate 		goto fail;
23827c478bd9Sstevel@tonic-gate 
23837c478bd9Sstevel@tonic-gate 	/*
23847c478bd9Sstevel@tonic-gate 	 * Now we use the delete stack to handle the possible unreferencing
23857c478bd9Sstevel@tonic-gate 	 * of oldsnapid.
23867c478bd9Sstevel@tonic-gate 	 */
23877c478bd9Sstevel@tonic-gate 	(void) memset(&dip, 0, sizeof (dip));
23887c478bd9Sstevel@tonic-gate 	dip.di_tx = tx;
23897c478bd9Sstevel@tonic-gate 	dip.di_np_tx = NULL;	/* no need for non-persistant backend */
23907c478bd9Sstevel@tonic-gate 
23917c478bd9Sstevel@tonic-gate 	if ((result = delete_stack_push(&dip, BACKEND_TYPE_NORMAL,
23927c478bd9Sstevel@tonic-gate 	    &snaplevel_tbl_delete, oldsnapid, 0)) != REP_PROTOCOL_SUCCESS)
23937c478bd9Sstevel@tonic-gate 		goto fail;
23947c478bd9Sstevel@tonic-gate 
23957c478bd9Sstevel@tonic-gate 	while (delete_stack_pop(&dip, &de)) {
23967c478bd9Sstevel@tonic-gate 		result = (*de.de_cb)(&dip, &de);
23977c478bd9Sstevel@tonic-gate 		if (result != REP_PROTOCOL_SUCCESS)
23987c478bd9Sstevel@tonic-gate 			goto fail;
23997c478bd9Sstevel@tonic-gate 	}
24007c478bd9Sstevel@tonic-gate 
24017c478bd9Sstevel@tonic-gate 	result = backend_tx_commit(tx);
24027c478bd9Sstevel@tonic-gate 	if (result != REP_PROTOCOL_SUCCESS)
24037c478bd9Sstevel@tonic-gate 		goto fail;
24047c478bd9Sstevel@tonic-gate 
24057c478bd9Sstevel@tonic-gate 	delete_stack_cleanup(&dip);
24067c478bd9Sstevel@tonic-gate 	*snapid_ptr = snapid;
24077c478bd9Sstevel@tonic-gate 	return (REP_PROTOCOL_SUCCESS);
24087c478bd9Sstevel@tonic-gate 
24097c478bd9Sstevel@tonic-gate fail:
24107c478bd9Sstevel@tonic-gate 	backend_tx_rollback(tx);
24117c478bd9Sstevel@tonic-gate 	delete_stack_cleanup(&dip);
24127c478bd9Sstevel@tonic-gate 	return (result);
24137c478bd9Sstevel@tonic-gate }
2414