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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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