1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * file_object.c - enter objects into and load them from the backend 31*0Sstevel@tonic-gate * 32*0Sstevel@tonic-gate * The primary entry points in this layer are object_create(), 33*0Sstevel@tonic-gate * object_create_pg(), object_delete(), and object_fill_children(). They each 34*0Sstevel@tonic-gate * take an rc_node_t and use the functions in the object_info_t info array for 35*0Sstevel@tonic-gate * the node's type. 36*0Sstevel@tonic-gate */ 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate #include <assert.h> 39*0Sstevel@tonic-gate #include <pthread.h> 40*0Sstevel@tonic-gate #include <stdio.h> 41*0Sstevel@tonic-gate #include <stdlib.h> 42*0Sstevel@tonic-gate #include <string.h> 43*0Sstevel@tonic-gate #include <strings.h> 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate #include "configd.h" 46*0Sstevel@tonic-gate #include "repcache_protocol.h" 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate typedef struct child_info { 49*0Sstevel@tonic-gate rc_node_t *ci_parent; 50*0Sstevel@tonic-gate backend_tx_t *ci_tx; /* only for properties */ 51*0Sstevel@tonic-gate rc_node_lookup_t ci_base_nl; 52*0Sstevel@tonic-gate } child_info_t; 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate typedef struct delete_ent delete_ent_t; 55*0Sstevel@tonic-gate typedef struct delete_stack delete_stack_t; 56*0Sstevel@tonic-gate typedef struct delete_info delete_info_t; 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate typedef int delete_cb_func(delete_info_t *, const delete_ent_t *); 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate struct delete_ent { 61*0Sstevel@tonic-gate delete_cb_func *de_cb; /* callback */ 62*0Sstevel@tonic-gate uint32_t de_backend; 63*0Sstevel@tonic-gate uint32_t de_id; 64*0Sstevel@tonic-gate uint32_t de_gen; /* only for property groups */ 65*0Sstevel@tonic-gate }; 66*0Sstevel@tonic-gate 67*0Sstevel@tonic-gate struct delete_stack { 68*0Sstevel@tonic-gate struct delete_stack *ds_next; 69*0Sstevel@tonic-gate uint32_t ds_size; /* number of elements */ 70*0Sstevel@tonic-gate uint32_t ds_cur; /* current offset */ 71*0Sstevel@tonic-gate delete_ent_t ds_buf[1]; /* actually ds_size */ 72*0Sstevel@tonic-gate }; 73*0Sstevel@tonic-gate #define DELETE_STACK_SIZE(x) offsetof(delete_stack_t, ds_buf[(x)]) 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate struct delete_info { 76*0Sstevel@tonic-gate backend_tx_t *di_tx; 77*0Sstevel@tonic-gate backend_tx_t *di_np_tx; 78*0Sstevel@tonic-gate delete_stack_t *di_stack; 79*0Sstevel@tonic-gate delete_stack_t *di_free; 80*0Sstevel@tonic-gate }; 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate typedef struct object_info { 83*0Sstevel@tonic-gate uint32_t obj_type; 84*0Sstevel@tonic-gate enum id_space obj_id_space; 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate int (*obj_fill_children)(rc_node_t *); 87*0Sstevel@tonic-gate int (*obj_setup_child_info)(rc_node_t *, uint32_t, child_info_t *); 88*0Sstevel@tonic-gate int (*obj_query_child)(backend_query_t *, rc_node_lookup_t *, 89*0Sstevel@tonic-gate const char *); 90*0Sstevel@tonic-gate int (*obj_insert_child)(backend_tx_t *, rc_node_lookup_t *, 91*0Sstevel@tonic-gate const char *); 92*0Sstevel@tonic-gate int (*obj_insert_pg_child)(backend_tx_t *, rc_node_lookup_t *, 93*0Sstevel@tonic-gate const char *, const char *, uint32_t, uint32_t); 94*0Sstevel@tonic-gate int (*obj_delete_start)(rc_node_t *, delete_info_t *); 95*0Sstevel@tonic-gate } object_info_t; 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate #define NUM_NEEDED 50 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate static int 100*0Sstevel@tonic-gate delete_stack_push(delete_info_t *dip, uint32_t be, delete_cb_func *cb, 101*0Sstevel@tonic-gate uint32_t id, uint32_t gen) 102*0Sstevel@tonic-gate { 103*0Sstevel@tonic-gate delete_stack_t *cur = dip->di_stack; 104*0Sstevel@tonic-gate delete_ent_t *ent; 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate if (cur == NULL || cur->ds_cur == cur->ds_size) { 107*0Sstevel@tonic-gate delete_stack_t *new = dip->di_free; 108*0Sstevel@tonic-gate dip->di_free = NULL; 109*0Sstevel@tonic-gate if (new == NULL) { 110*0Sstevel@tonic-gate new = uu_zalloc(DELETE_STACK_SIZE(NUM_NEEDED)); 111*0Sstevel@tonic-gate if (new == NULL) 112*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_NO_RESOURCES); 113*0Sstevel@tonic-gate new->ds_size = NUM_NEEDED; 114*0Sstevel@tonic-gate } 115*0Sstevel@tonic-gate new->ds_cur = 0; 116*0Sstevel@tonic-gate new->ds_next = dip->di_stack; 117*0Sstevel@tonic-gate dip->di_stack = new; 118*0Sstevel@tonic-gate cur = new; 119*0Sstevel@tonic-gate } 120*0Sstevel@tonic-gate assert(cur->ds_cur < cur->ds_size); 121*0Sstevel@tonic-gate ent = &cur->ds_buf[cur->ds_cur++]; 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate ent->de_backend = be; 124*0Sstevel@tonic-gate ent->de_cb = cb; 125*0Sstevel@tonic-gate ent->de_id = id; 126*0Sstevel@tonic-gate ent->de_gen = gen; 127*0Sstevel@tonic-gate 128*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 129*0Sstevel@tonic-gate } 130*0Sstevel@tonic-gate 131*0Sstevel@tonic-gate static int 132*0Sstevel@tonic-gate delete_stack_pop(delete_info_t *dip, delete_ent_t *out) 133*0Sstevel@tonic-gate { 134*0Sstevel@tonic-gate delete_stack_t *cur = dip->di_stack; 135*0Sstevel@tonic-gate delete_ent_t *ent; 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate if (cur == NULL) 138*0Sstevel@tonic-gate return (NULL); 139*0Sstevel@tonic-gate assert(cur->ds_cur > 0 && cur->ds_cur <= cur->ds_size); 140*0Sstevel@tonic-gate ent = &cur->ds_buf[--cur->ds_cur]; 141*0Sstevel@tonic-gate if (cur->ds_cur == 0) { 142*0Sstevel@tonic-gate dip->di_stack = cur->ds_next; 143*0Sstevel@tonic-gate cur->ds_next = NULL; 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate if (dip->di_free != NULL) 146*0Sstevel@tonic-gate uu_free(dip->di_free); 147*0Sstevel@tonic-gate dip->di_free = cur; 148*0Sstevel@tonic-gate } 149*0Sstevel@tonic-gate if (ent == NULL) 150*0Sstevel@tonic-gate return (0); 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate *out = *ent; 153*0Sstevel@tonic-gate return (1); 154*0Sstevel@tonic-gate } 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate static void 157*0Sstevel@tonic-gate delete_stack_cleanup(delete_info_t *dip) 158*0Sstevel@tonic-gate { 159*0Sstevel@tonic-gate delete_stack_t *cur; 160*0Sstevel@tonic-gate while ((cur = dip->di_stack) != NULL) { 161*0Sstevel@tonic-gate dip->di_stack = cur->ds_next; 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate uu_free(cur); 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate if ((cur = dip->di_free) != NULL) { 167*0Sstevel@tonic-gate assert(cur->ds_next == NULL); /* should only be one */ 168*0Sstevel@tonic-gate uu_free(cur); 169*0Sstevel@tonic-gate dip->di_free = NULL; 170*0Sstevel@tonic-gate } 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate struct delete_cb_info { 174*0Sstevel@tonic-gate delete_info_t *dci_dip; 175*0Sstevel@tonic-gate uint32_t dci_be; 176*0Sstevel@tonic-gate delete_cb_func *dci_cb; 177*0Sstevel@tonic-gate int dci_result; 178*0Sstevel@tonic-gate }; 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate /*ARGSUSED*/ 181*0Sstevel@tonic-gate static int 182*0Sstevel@tonic-gate push_delete_callback(void *data, int columns, char **vals, char **names) 183*0Sstevel@tonic-gate { 184*0Sstevel@tonic-gate struct delete_cb_info *info = data; 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate const char *id_str = *vals++; 187*0Sstevel@tonic-gate const char *gen_str = *vals++; 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gate uint32_t id; 190*0Sstevel@tonic-gate uint32_t gen; 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate assert(columns == 2); 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate if (uu_strtouint(id_str, &id, sizeof (id), 0, 0, 0) == -1) 195*0Sstevel@tonic-gate backend_panic("invalid integer in database"); 196*0Sstevel@tonic-gate if (uu_strtouint(gen_str, &gen, sizeof (gen), 0, 0, 0) == -1) 197*0Sstevel@tonic-gate backend_panic("invalid integer in database"); 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate info->dci_result = delete_stack_push(info->dci_dip, info->dci_be, 200*0Sstevel@tonic-gate info->dci_cb, id, gen); 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate if (info->dci_result != REP_PROTOCOL_SUCCESS) 203*0Sstevel@tonic-gate return (BACKEND_CALLBACK_ABORT); 204*0Sstevel@tonic-gate return (BACKEND_CALLBACK_CONTINUE); 205*0Sstevel@tonic-gate } 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate static int 208*0Sstevel@tonic-gate value_delete(delete_info_t *dip, const delete_ent_t *ent) 209*0Sstevel@tonic-gate { 210*0Sstevel@tonic-gate uint32_t be = ent->de_backend; 211*0Sstevel@tonic-gate int r; 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate backend_query_t *q; 214*0Sstevel@tonic-gate 215*0Sstevel@tonic-gate backend_tx_t *tx = (be == BACKEND_TYPE_NORMAL)? dip->di_tx : 216*0Sstevel@tonic-gate dip->di_np_tx; 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate q = backend_query_alloc(); 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate backend_query_add(q, 221*0Sstevel@tonic-gate "SELECT 1 FROM prop_lnk_tbl WHERE (lnk_val_id = %d); " 222*0Sstevel@tonic-gate "DELETE FROM value_tbl WHERE (value_id = %d); ", 223*0Sstevel@tonic-gate ent->de_id, ent->de_id); 224*0Sstevel@tonic-gate r = backend_tx_run(tx, q, backend_fail_if_seen, NULL); 225*0Sstevel@tonic-gate backend_query_free(q); 226*0Sstevel@tonic-gate if (r == REP_PROTOCOL_DONE) 227*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); /* still in use */ 228*0Sstevel@tonic-gate return (r); 229*0Sstevel@tonic-gate } 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate static int 232*0Sstevel@tonic-gate pg_lnk_tbl_delete(delete_info_t *dip, const delete_ent_t *ent) 233*0Sstevel@tonic-gate { 234*0Sstevel@tonic-gate struct delete_cb_info info; 235*0Sstevel@tonic-gate uint32_t be = ent->de_backend; 236*0Sstevel@tonic-gate int r; 237*0Sstevel@tonic-gate 238*0Sstevel@tonic-gate backend_query_t *q; 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate backend_tx_t *tx = (be == BACKEND_TYPE_NORMAL)? dip->di_tx : 241*0Sstevel@tonic-gate dip->di_np_tx; 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate /* 244*0Sstevel@tonic-gate * For non-persistent backends, we could only have one parent, and 245*0Sstevel@tonic-gate * he's already been deleted. 246*0Sstevel@tonic-gate * 247*0Sstevel@tonic-gate * For normal backends, we need to check to see if we're in 248*0Sstevel@tonic-gate * a snapshot or are the active generation for the property 249*0Sstevel@tonic-gate * group. If we are, there's nothing to be done. 250*0Sstevel@tonic-gate */ 251*0Sstevel@tonic-gate if (be == BACKEND_TYPE_NORMAL) { 252*0Sstevel@tonic-gate q = backend_query_alloc(); 253*0Sstevel@tonic-gate backend_query_add(q, 254*0Sstevel@tonic-gate "SELECT 1 " 255*0Sstevel@tonic-gate "FROM pg_tbl " 256*0Sstevel@tonic-gate "WHERE (pg_id = %d AND pg_gen_id = %d); " 257*0Sstevel@tonic-gate "SELECT 1 " 258*0Sstevel@tonic-gate "FROM snaplevel_lnk_tbl " 259*0Sstevel@tonic-gate "WHERE (snaplvl_pg_id = %d AND snaplvl_gen_id = %d);", 260*0Sstevel@tonic-gate ent->de_id, ent->de_gen, 261*0Sstevel@tonic-gate ent->de_id, ent->de_gen); 262*0Sstevel@tonic-gate r = backend_tx_run(tx, q, backend_fail_if_seen, NULL); 263*0Sstevel@tonic-gate backend_query_free(q); 264*0Sstevel@tonic-gate 265*0Sstevel@tonic-gate if (r == REP_PROTOCOL_DONE) 266*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); /* still in use */ 267*0Sstevel@tonic-gate } 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate info.dci_dip = dip; 270*0Sstevel@tonic-gate info.dci_be = be; 271*0Sstevel@tonic-gate info.dci_cb = &value_delete; 272*0Sstevel@tonic-gate info.dci_result = REP_PROTOCOL_SUCCESS; 273*0Sstevel@tonic-gate 274*0Sstevel@tonic-gate q = backend_query_alloc(); 275*0Sstevel@tonic-gate backend_query_add(q, 276*0Sstevel@tonic-gate "SELECT DISTINCT lnk_val_id, 0 FROM prop_lnk_tbl " 277*0Sstevel@tonic-gate "WHERE " 278*0Sstevel@tonic-gate " (lnk_pg_id = %d AND lnk_gen_id = %d AND lnk_val_id NOTNULL); " 279*0Sstevel@tonic-gate "DELETE FROM prop_lnk_tbl " 280*0Sstevel@tonic-gate "WHERE (lnk_pg_id = %d AND lnk_gen_id = %d)", 281*0Sstevel@tonic-gate ent->de_id, ent->de_gen, ent->de_id, ent->de_gen); 282*0Sstevel@tonic-gate 283*0Sstevel@tonic-gate r = backend_tx_run(tx, q, push_delete_callback, &info); 284*0Sstevel@tonic-gate backend_query_free(q); 285*0Sstevel@tonic-gate 286*0Sstevel@tonic-gate if (r == REP_PROTOCOL_DONE) { 287*0Sstevel@tonic-gate assert(info.dci_result != REP_PROTOCOL_SUCCESS); 288*0Sstevel@tonic-gate return (info.dci_result); 289*0Sstevel@tonic-gate } 290*0Sstevel@tonic-gate return (r); 291*0Sstevel@tonic-gate } 292*0Sstevel@tonic-gate 293*0Sstevel@tonic-gate static int 294*0Sstevel@tonic-gate propertygrp_delete(delete_info_t *dip, const delete_ent_t *ent) 295*0Sstevel@tonic-gate { 296*0Sstevel@tonic-gate uint32_t be = ent->de_backend; 297*0Sstevel@tonic-gate backend_query_t *q; 298*0Sstevel@tonic-gate uint32_t gen; 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate int r; 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate backend_tx_t *tx = (be == BACKEND_TYPE_NORMAL)? dip->di_tx : 303*0Sstevel@tonic-gate dip->di_np_tx; 304*0Sstevel@tonic-gate 305*0Sstevel@tonic-gate q = backend_query_alloc(); 306*0Sstevel@tonic-gate backend_query_add(q, 307*0Sstevel@tonic-gate "SELECT pg_gen_id FROM pg_tbl WHERE pg_id = %d; " 308*0Sstevel@tonic-gate "DELETE FROM pg_tbl WHERE pg_id = %d", 309*0Sstevel@tonic-gate ent->de_id, ent->de_id); 310*0Sstevel@tonic-gate r = backend_tx_run_single_int(tx, q, &gen); 311*0Sstevel@tonic-gate backend_query_free(q); 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate if (r != REP_PROTOCOL_SUCCESS) 314*0Sstevel@tonic-gate return (r); 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate return (delete_stack_push(dip, be, &pg_lnk_tbl_delete, 317*0Sstevel@tonic-gate ent->de_id, gen)); 318*0Sstevel@tonic-gate } 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate static int 321*0Sstevel@tonic-gate snaplevel_lnk_delete(delete_info_t *dip, const delete_ent_t *ent) 322*0Sstevel@tonic-gate { 323*0Sstevel@tonic-gate uint32_t be = ent->de_backend; 324*0Sstevel@tonic-gate backend_query_t *q; 325*0Sstevel@tonic-gate struct delete_cb_info info; 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate int r; 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate backend_tx_t *tx = (be == BACKEND_TYPE_NORMAL)? dip->di_tx : 330*0Sstevel@tonic-gate dip->di_np_tx; 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate info.dci_dip = dip; 333*0Sstevel@tonic-gate info.dci_be = be; 334*0Sstevel@tonic-gate info.dci_cb = &pg_lnk_tbl_delete; 335*0Sstevel@tonic-gate info.dci_result = REP_PROTOCOL_SUCCESS; 336*0Sstevel@tonic-gate 337*0Sstevel@tonic-gate q = backend_query_alloc(); 338*0Sstevel@tonic-gate backend_query_add(q, 339*0Sstevel@tonic-gate "SELECT snaplvl_pg_id, snaplvl_gen_id " 340*0Sstevel@tonic-gate " FROM snaplevel_lnk_tbl " 341*0Sstevel@tonic-gate " WHERE snaplvl_level_id = %d; " 342*0Sstevel@tonic-gate "DELETE FROM snaplevel_lnk_tbl WHERE snaplvl_level_id = %d", 343*0Sstevel@tonic-gate ent->de_id, ent->de_id); 344*0Sstevel@tonic-gate r = backend_tx_run(tx, q, push_delete_callback, &info); 345*0Sstevel@tonic-gate backend_query_free(q); 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate if (r == REP_PROTOCOL_DONE) { 348*0Sstevel@tonic-gate assert(info.dci_result != REP_PROTOCOL_SUCCESS); 349*0Sstevel@tonic-gate return (info.dci_result); 350*0Sstevel@tonic-gate } 351*0Sstevel@tonic-gate return (r); 352*0Sstevel@tonic-gate } 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate static int 355*0Sstevel@tonic-gate snaplevel_tbl_delete(delete_info_t *dip, const delete_ent_t *ent) 356*0Sstevel@tonic-gate { 357*0Sstevel@tonic-gate uint32_t be = ent->de_backend; 358*0Sstevel@tonic-gate backend_tx_t *tx = (be == BACKEND_TYPE_NORMAL)? dip->di_tx : 359*0Sstevel@tonic-gate dip->di_np_tx; 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate struct delete_cb_info info; 362*0Sstevel@tonic-gate backend_query_t *q; 363*0Sstevel@tonic-gate int r; 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate assert(be == BACKEND_TYPE_NORMAL); 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate q = backend_query_alloc(); 368*0Sstevel@tonic-gate backend_query_add(q, 369*0Sstevel@tonic-gate "SELECT 1 FROM snapshot_lnk_tbl WHERE lnk_snap_id = %d", 370*0Sstevel@tonic-gate ent->de_id); 371*0Sstevel@tonic-gate r = backend_tx_run(tx, q, backend_fail_if_seen, NULL); 372*0Sstevel@tonic-gate backend_query_free(q); 373*0Sstevel@tonic-gate 374*0Sstevel@tonic-gate if (r == REP_PROTOCOL_DONE) 375*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); /* still in use */ 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate info.dci_dip = dip; 378*0Sstevel@tonic-gate info.dci_be = be; 379*0Sstevel@tonic-gate info.dci_cb = &snaplevel_lnk_delete; 380*0Sstevel@tonic-gate info.dci_result = REP_PROTOCOL_SUCCESS; 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate q = backend_query_alloc(); 383*0Sstevel@tonic-gate backend_query_add(q, 384*0Sstevel@tonic-gate "SELECT snap_level_id, 0 FROM snaplevel_tbl WHERE snap_id = %d;" 385*0Sstevel@tonic-gate "DELETE FROM snaplevel_tbl WHERE snap_id = %d", 386*0Sstevel@tonic-gate ent->de_id, ent->de_id); 387*0Sstevel@tonic-gate r = backend_tx_run(tx, q, push_delete_callback, &info); 388*0Sstevel@tonic-gate backend_query_free(q); 389*0Sstevel@tonic-gate 390*0Sstevel@tonic-gate if (r == REP_PROTOCOL_DONE) { 391*0Sstevel@tonic-gate assert(info.dci_result != REP_PROTOCOL_SUCCESS); 392*0Sstevel@tonic-gate return (info.dci_result); 393*0Sstevel@tonic-gate } 394*0Sstevel@tonic-gate return (r); 395*0Sstevel@tonic-gate } 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate static int 398*0Sstevel@tonic-gate snapshot_lnk_delete(delete_info_t *dip, const delete_ent_t *ent) 399*0Sstevel@tonic-gate { 400*0Sstevel@tonic-gate uint32_t be = ent->de_backend; 401*0Sstevel@tonic-gate backend_tx_t *tx = (be == BACKEND_TYPE_NORMAL)? dip->di_tx : 402*0Sstevel@tonic-gate dip->di_np_tx; 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate backend_query_t *q; 405*0Sstevel@tonic-gate uint32_t snapid; 406*0Sstevel@tonic-gate int r; 407*0Sstevel@tonic-gate 408*0Sstevel@tonic-gate assert(be == BACKEND_TYPE_NORMAL); 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate q = backend_query_alloc(); 411*0Sstevel@tonic-gate backend_query_add(q, 412*0Sstevel@tonic-gate "SELECT lnk_snap_id FROM snapshot_lnk_tbl WHERE lnk_id = %d; " 413*0Sstevel@tonic-gate "DELETE FROM snapshot_lnk_tbl WHERE lnk_id = %d", 414*0Sstevel@tonic-gate ent->de_id, ent->de_id); 415*0Sstevel@tonic-gate r = backend_tx_run_single_int(tx, q, &snapid); 416*0Sstevel@tonic-gate backend_query_free(q); 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate if (r != REP_PROTOCOL_SUCCESS) 419*0Sstevel@tonic-gate return (r); 420*0Sstevel@tonic-gate 421*0Sstevel@tonic-gate return (delete_stack_push(dip, be, &snaplevel_tbl_delete, snapid, 0)); 422*0Sstevel@tonic-gate } 423*0Sstevel@tonic-gate 424*0Sstevel@tonic-gate static int 425*0Sstevel@tonic-gate pgparent_delete_add_pgs(delete_info_t *dip, uint32_t parent_id) 426*0Sstevel@tonic-gate { 427*0Sstevel@tonic-gate struct delete_cb_info info; 428*0Sstevel@tonic-gate backend_query_t *q; 429*0Sstevel@tonic-gate int r; 430*0Sstevel@tonic-gate 431*0Sstevel@tonic-gate info.dci_dip = dip; 432*0Sstevel@tonic-gate info.dci_be = BACKEND_TYPE_NORMAL; 433*0Sstevel@tonic-gate info.dci_cb = &propertygrp_delete; 434*0Sstevel@tonic-gate info.dci_result = REP_PROTOCOL_SUCCESS; 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate q = backend_query_alloc(); 437*0Sstevel@tonic-gate backend_query_add(q, 438*0Sstevel@tonic-gate "SELECT pg_id, 0 FROM pg_tbl WHERE pg_parent_id = %d", 439*0Sstevel@tonic-gate parent_id); 440*0Sstevel@tonic-gate 441*0Sstevel@tonic-gate r = backend_tx_run(dip->di_tx, q, push_delete_callback, &info); 442*0Sstevel@tonic-gate 443*0Sstevel@tonic-gate if (r == REP_PROTOCOL_DONE) { 444*0Sstevel@tonic-gate assert(info.dci_result != REP_PROTOCOL_SUCCESS); 445*0Sstevel@tonic-gate backend_query_free(q); 446*0Sstevel@tonic-gate return (info.dci_result); 447*0Sstevel@tonic-gate } 448*0Sstevel@tonic-gate if (r != REP_PROTOCOL_SUCCESS) { 449*0Sstevel@tonic-gate backend_query_free(q); 450*0Sstevel@tonic-gate return (r); 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate if (dip->di_np_tx != NULL) { 454*0Sstevel@tonic-gate info.dci_be = BACKEND_TYPE_NONPERSIST; 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate r = backend_tx_run(dip->di_np_tx, q, push_delete_callback, 457*0Sstevel@tonic-gate &info); 458*0Sstevel@tonic-gate 459*0Sstevel@tonic-gate if (r == REP_PROTOCOL_DONE) { 460*0Sstevel@tonic-gate assert(info.dci_result != REP_PROTOCOL_SUCCESS); 461*0Sstevel@tonic-gate backend_query_free(q); 462*0Sstevel@tonic-gate return (info.dci_result); 463*0Sstevel@tonic-gate } 464*0Sstevel@tonic-gate if (r != REP_PROTOCOL_SUCCESS) { 465*0Sstevel@tonic-gate backend_query_free(q); 466*0Sstevel@tonic-gate return (r); 467*0Sstevel@tonic-gate } 468*0Sstevel@tonic-gate } 469*0Sstevel@tonic-gate backend_query_free(q); 470*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 471*0Sstevel@tonic-gate } 472*0Sstevel@tonic-gate 473*0Sstevel@tonic-gate static int 474*0Sstevel@tonic-gate service_delete(delete_info_t *dip, const delete_ent_t *ent) 475*0Sstevel@tonic-gate { 476*0Sstevel@tonic-gate int r; 477*0Sstevel@tonic-gate 478*0Sstevel@tonic-gate r = backend_tx_run_update_changed(dip->di_tx, 479*0Sstevel@tonic-gate "DELETE FROM service_tbl WHERE svc_id = %d", ent->de_id); 480*0Sstevel@tonic-gate if (r != REP_PROTOCOL_SUCCESS) 481*0Sstevel@tonic-gate return (r); 482*0Sstevel@tonic-gate 483*0Sstevel@tonic-gate return (pgparent_delete_add_pgs(dip, ent->de_id)); 484*0Sstevel@tonic-gate } 485*0Sstevel@tonic-gate 486*0Sstevel@tonic-gate static int 487*0Sstevel@tonic-gate instance_delete(delete_info_t *dip, const delete_ent_t *ent) 488*0Sstevel@tonic-gate { 489*0Sstevel@tonic-gate struct delete_cb_info info; 490*0Sstevel@tonic-gate int r; 491*0Sstevel@tonic-gate backend_query_t *q; 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gate r = backend_tx_run_update_changed(dip->di_tx, 494*0Sstevel@tonic-gate "DELETE FROM instance_tbl WHERE instance_id = %d", ent->de_id); 495*0Sstevel@tonic-gate if (r != REP_PROTOCOL_SUCCESS) 496*0Sstevel@tonic-gate return (r); 497*0Sstevel@tonic-gate 498*0Sstevel@tonic-gate r = pgparent_delete_add_pgs(dip, ent->de_id); 499*0Sstevel@tonic-gate if (r != REP_PROTOCOL_SUCCESS) 500*0Sstevel@tonic-gate return (r); 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate info.dci_dip = dip; 503*0Sstevel@tonic-gate info.dci_be = BACKEND_TYPE_NORMAL; 504*0Sstevel@tonic-gate info.dci_cb = &snapshot_lnk_delete; 505*0Sstevel@tonic-gate info.dci_result = REP_PROTOCOL_SUCCESS; 506*0Sstevel@tonic-gate 507*0Sstevel@tonic-gate q = backend_query_alloc(); 508*0Sstevel@tonic-gate backend_query_add(q, 509*0Sstevel@tonic-gate "SELECT lnk_id, 0 FROM snapshot_lnk_tbl WHERE lnk_inst_id = %d", 510*0Sstevel@tonic-gate ent->de_id); 511*0Sstevel@tonic-gate r = backend_tx_run(dip->di_tx, q, push_delete_callback, &info); 512*0Sstevel@tonic-gate backend_query_free(q); 513*0Sstevel@tonic-gate 514*0Sstevel@tonic-gate if (r == REP_PROTOCOL_DONE) { 515*0Sstevel@tonic-gate assert(info.dci_result != REP_PROTOCOL_SUCCESS); 516*0Sstevel@tonic-gate return (info.dci_result); 517*0Sstevel@tonic-gate } 518*0Sstevel@tonic-gate return (r); 519*0Sstevel@tonic-gate } 520*0Sstevel@tonic-gate 521*0Sstevel@tonic-gate /*ARGSUSED*/ 522*0Sstevel@tonic-gate static int 523*0Sstevel@tonic-gate fill_child_callback(void *data, int columns, char **vals, char **names) 524*0Sstevel@tonic-gate { 525*0Sstevel@tonic-gate child_info_t *cp = data; 526*0Sstevel@tonic-gate rc_node_t *np; 527*0Sstevel@tonic-gate uint32_t main_id; 528*0Sstevel@tonic-gate const char *name; 529*0Sstevel@tonic-gate const char *cur; 530*0Sstevel@tonic-gate rc_node_lookup_t *lp = &cp->ci_base_nl; 531*0Sstevel@tonic-gate 532*0Sstevel@tonic-gate assert(columns == 2); 533*0Sstevel@tonic-gate 534*0Sstevel@tonic-gate name = *vals++; 535*0Sstevel@tonic-gate columns--; 536*0Sstevel@tonic-gate 537*0Sstevel@tonic-gate cur = *vals++; 538*0Sstevel@tonic-gate columns--; 539*0Sstevel@tonic-gate if (uu_strtouint(cur, &main_id, sizeof (main_id), 0, 0, 0) == -1) 540*0Sstevel@tonic-gate backend_panic("invalid integer in database"); 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate lp->rl_main_id = main_id; 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate if ((np = rc_node_alloc()) == NULL) 545*0Sstevel@tonic-gate return (BACKEND_CALLBACK_ABORT); 546*0Sstevel@tonic-gate 547*0Sstevel@tonic-gate np = rc_node_setup(np, lp, name, cp->ci_parent); 548*0Sstevel@tonic-gate rc_node_rele(np); 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate return (BACKEND_CALLBACK_CONTINUE); 551*0Sstevel@tonic-gate } 552*0Sstevel@tonic-gate 553*0Sstevel@tonic-gate /*ARGSUSED*/ 554*0Sstevel@tonic-gate static int 555*0Sstevel@tonic-gate fill_snapshot_callback(void *data, int columns, char **vals, char **names) 556*0Sstevel@tonic-gate { 557*0Sstevel@tonic-gate child_info_t *cp = data; 558*0Sstevel@tonic-gate rc_node_t *np; 559*0Sstevel@tonic-gate uint32_t main_id; 560*0Sstevel@tonic-gate uint32_t snap_id; 561*0Sstevel@tonic-gate const char *name; 562*0Sstevel@tonic-gate const char *cur; 563*0Sstevel@tonic-gate const char *snap; 564*0Sstevel@tonic-gate rc_node_lookup_t *lp = &cp->ci_base_nl; 565*0Sstevel@tonic-gate 566*0Sstevel@tonic-gate assert(columns == 3); 567*0Sstevel@tonic-gate 568*0Sstevel@tonic-gate name = *vals++; 569*0Sstevel@tonic-gate columns--; 570*0Sstevel@tonic-gate 571*0Sstevel@tonic-gate cur = *vals++; 572*0Sstevel@tonic-gate columns--; 573*0Sstevel@tonic-gate snap = *vals++; 574*0Sstevel@tonic-gate columns--; 575*0Sstevel@tonic-gate if (uu_strtouint(cur, &main_id, sizeof (main_id), 0, 0, 0) == -1 || 576*0Sstevel@tonic-gate uu_strtouint(snap, &snap_id, sizeof (snap_id), 0, 0, 0) == -1) 577*0Sstevel@tonic-gate backend_panic("invalid integer in database"); 578*0Sstevel@tonic-gate 579*0Sstevel@tonic-gate lp->rl_main_id = main_id; 580*0Sstevel@tonic-gate 581*0Sstevel@tonic-gate if ((np = rc_node_alloc()) == NULL) 582*0Sstevel@tonic-gate return (BACKEND_CALLBACK_ABORT); 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate np = rc_node_setup_snapshot(np, lp, name, snap_id, cp->ci_parent); 585*0Sstevel@tonic-gate rc_node_rele(np); 586*0Sstevel@tonic-gate 587*0Sstevel@tonic-gate return (BACKEND_CALLBACK_CONTINUE); 588*0Sstevel@tonic-gate } 589*0Sstevel@tonic-gate 590*0Sstevel@tonic-gate /*ARGSUSED*/ 591*0Sstevel@tonic-gate static int 592*0Sstevel@tonic-gate fill_pg_callback(void *data, int columns, char **vals, char **names) 593*0Sstevel@tonic-gate { 594*0Sstevel@tonic-gate child_info_t *cip = data; 595*0Sstevel@tonic-gate const char *name; 596*0Sstevel@tonic-gate const char *type; 597*0Sstevel@tonic-gate const char *cur; 598*0Sstevel@tonic-gate uint32_t main_id; 599*0Sstevel@tonic-gate uint32_t flags; 600*0Sstevel@tonic-gate uint32_t gen_id; 601*0Sstevel@tonic-gate 602*0Sstevel@tonic-gate rc_node_lookup_t *lp = &cip->ci_base_nl; 603*0Sstevel@tonic-gate rc_node_t *newnode, *pg; 604*0Sstevel@tonic-gate 605*0Sstevel@tonic-gate assert(columns == 5); 606*0Sstevel@tonic-gate 607*0Sstevel@tonic-gate name = *vals++; /* pg_name */ 608*0Sstevel@tonic-gate columns--; 609*0Sstevel@tonic-gate 610*0Sstevel@tonic-gate cur = *vals++; /* pg_id */ 611*0Sstevel@tonic-gate columns--; 612*0Sstevel@tonic-gate if (uu_strtouint(cur, &main_id, sizeof (main_id), 0, 0, 0) == -1) 613*0Sstevel@tonic-gate backend_panic("invalid integer in database"); 614*0Sstevel@tonic-gate 615*0Sstevel@tonic-gate lp->rl_main_id = main_id; 616*0Sstevel@tonic-gate 617*0Sstevel@tonic-gate cur = *vals++; /* pg_gen_id */ 618*0Sstevel@tonic-gate columns--; 619*0Sstevel@tonic-gate if (uu_strtouint(cur, &gen_id, sizeof (gen_id), 0, 0, 0) == -1) 620*0Sstevel@tonic-gate backend_panic("invalid integer in database"); 621*0Sstevel@tonic-gate 622*0Sstevel@tonic-gate type = *vals++; /* pg_type */ 623*0Sstevel@tonic-gate columns--; 624*0Sstevel@tonic-gate 625*0Sstevel@tonic-gate cur = *vals++; /* pg_flags */ 626*0Sstevel@tonic-gate columns--; 627*0Sstevel@tonic-gate if (uu_strtouint(cur, &flags, sizeof (flags), 0, 0, 0) == -1) 628*0Sstevel@tonic-gate backend_panic("invalid integer in database"); 629*0Sstevel@tonic-gate 630*0Sstevel@tonic-gate if ((newnode = rc_node_alloc()) == NULL) 631*0Sstevel@tonic-gate return (BACKEND_CALLBACK_ABORT); 632*0Sstevel@tonic-gate 633*0Sstevel@tonic-gate pg = rc_node_setup_pg(newnode, lp, name, type, flags, gen_id, 634*0Sstevel@tonic-gate cip->ci_parent); 635*0Sstevel@tonic-gate if (pg == NULL) { 636*0Sstevel@tonic-gate rc_node_destroy(newnode); 637*0Sstevel@tonic-gate return (BACKEND_CALLBACK_ABORT); 638*0Sstevel@tonic-gate } 639*0Sstevel@tonic-gate 640*0Sstevel@tonic-gate rc_node_rele(pg); 641*0Sstevel@tonic-gate 642*0Sstevel@tonic-gate return (BACKEND_CALLBACK_CONTINUE); 643*0Sstevel@tonic-gate } 644*0Sstevel@tonic-gate 645*0Sstevel@tonic-gate struct property_value_info { 646*0Sstevel@tonic-gate char *pvi_base; 647*0Sstevel@tonic-gate size_t pvi_pos; 648*0Sstevel@tonic-gate size_t pvi_size; 649*0Sstevel@tonic-gate size_t pvi_count; 650*0Sstevel@tonic-gate }; 651*0Sstevel@tonic-gate 652*0Sstevel@tonic-gate /*ARGSUSED*/ 653*0Sstevel@tonic-gate static int 654*0Sstevel@tonic-gate property_value_size_cb(void *data, int columns, char **vals, char **names) 655*0Sstevel@tonic-gate { 656*0Sstevel@tonic-gate struct property_value_info *info = data; 657*0Sstevel@tonic-gate assert(columns == 1); 658*0Sstevel@tonic-gate 659*0Sstevel@tonic-gate info->pvi_size += strlen(vals[0]) + 1; /* count the '\0' */ 660*0Sstevel@tonic-gate 661*0Sstevel@tonic-gate return (BACKEND_CALLBACK_CONTINUE); 662*0Sstevel@tonic-gate } 663*0Sstevel@tonic-gate 664*0Sstevel@tonic-gate /*ARGSUSED*/ 665*0Sstevel@tonic-gate static int 666*0Sstevel@tonic-gate property_value_cb(void *data, int columns, char **vals, char **names) 667*0Sstevel@tonic-gate { 668*0Sstevel@tonic-gate struct property_value_info *info = data; 669*0Sstevel@tonic-gate size_t pos, left, len; 670*0Sstevel@tonic-gate 671*0Sstevel@tonic-gate assert(columns == 1); 672*0Sstevel@tonic-gate pos = info->pvi_pos; 673*0Sstevel@tonic-gate left = info->pvi_size - pos; 674*0Sstevel@tonic-gate 675*0Sstevel@tonic-gate pos = info->pvi_pos; 676*0Sstevel@tonic-gate left = info->pvi_size - pos; 677*0Sstevel@tonic-gate 678*0Sstevel@tonic-gate if ((len = strlcpy(&info->pvi_base[pos], vals[0], left)) >= left) { 679*0Sstevel@tonic-gate /* 680*0Sstevel@tonic-gate * since we preallocated, above, this shouldn't happen 681*0Sstevel@tonic-gate */ 682*0Sstevel@tonic-gate backend_panic("unexpected database change"); 683*0Sstevel@tonic-gate } 684*0Sstevel@tonic-gate 685*0Sstevel@tonic-gate len += 1; /* count the '\0' */ 686*0Sstevel@tonic-gate 687*0Sstevel@tonic-gate info->pvi_pos += len; 688*0Sstevel@tonic-gate info->pvi_count++; 689*0Sstevel@tonic-gate 690*0Sstevel@tonic-gate return (BACKEND_CALLBACK_CONTINUE); 691*0Sstevel@tonic-gate } 692*0Sstevel@tonic-gate 693*0Sstevel@tonic-gate /*ARGSUSED*/ 694*0Sstevel@tonic-gate void 695*0Sstevel@tonic-gate object_free_values(const char *vals, uint32_t type, size_t count, size_t size) 696*0Sstevel@tonic-gate { 697*0Sstevel@tonic-gate if (vals != NULL) 698*0Sstevel@tonic-gate uu_free((void *)vals); 699*0Sstevel@tonic-gate } 700*0Sstevel@tonic-gate 701*0Sstevel@tonic-gate /*ARGSUSED*/ 702*0Sstevel@tonic-gate static int 703*0Sstevel@tonic-gate fill_property_callback(void *data, int columns, char **vals, char **names) 704*0Sstevel@tonic-gate { 705*0Sstevel@tonic-gate child_info_t *cp = data; 706*0Sstevel@tonic-gate backend_tx_t *tx = cp->ci_tx; 707*0Sstevel@tonic-gate uint32_t main_id; 708*0Sstevel@tonic-gate const char *name; 709*0Sstevel@tonic-gate const char *cur; 710*0Sstevel@tonic-gate rep_protocol_value_type_t type; 711*0Sstevel@tonic-gate rc_node_lookup_t *lp = &cp->ci_base_nl; 712*0Sstevel@tonic-gate struct property_value_info info; 713*0Sstevel@tonic-gate int rc; 714*0Sstevel@tonic-gate 715*0Sstevel@tonic-gate assert(columns == 4); 716*0Sstevel@tonic-gate assert(tx != NULL); 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate info.pvi_base = NULL; 719*0Sstevel@tonic-gate info.pvi_pos = 0; 720*0Sstevel@tonic-gate info.pvi_size = 0; 721*0Sstevel@tonic-gate info.pvi_count = 0; 722*0Sstevel@tonic-gate 723*0Sstevel@tonic-gate name = *vals++; 724*0Sstevel@tonic-gate 725*0Sstevel@tonic-gate cur = *vals++; 726*0Sstevel@tonic-gate if (uu_strtouint(cur, &main_id, sizeof (main_id), 0, 0, 0) == -1) 727*0Sstevel@tonic-gate backend_panic("invalid integer in database"); 728*0Sstevel@tonic-gate 729*0Sstevel@tonic-gate cur = *vals++; 730*0Sstevel@tonic-gate assert(('a' <= cur[0] && 'z' >= cur[0]) || 731*0Sstevel@tonic-gate ('A' <= cur[0] && 'Z' >= cur[0]) && 732*0Sstevel@tonic-gate (cur[1] == 0 || ('a' <= cur[1] && 'z' >= cur[1]) || 733*0Sstevel@tonic-gate ('A' <= cur[1] && 'Z' >= cur[1]))); 734*0Sstevel@tonic-gate type = cur[0] | (cur[1] << 8); 735*0Sstevel@tonic-gate 736*0Sstevel@tonic-gate lp->rl_main_id = main_id; 737*0Sstevel@tonic-gate 738*0Sstevel@tonic-gate /* 739*0Sstevel@tonic-gate * fill in the values, if any 740*0Sstevel@tonic-gate */ 741*0Sstevel@tonic-gate if ((cur = *vals++) != NULL) { 742*0Sstevel@tonic-gate rep_protocol_responseid_t r; 743*0Sstevel@tonic-gate backend_query_t *q = backend_query_alloc(); 744*0Sstevel@tonic-gate 745*0Sstevel@tonic-gate backend_query_add(q, 746*0Sstevel@tonic-gate "SELECT value_value FROM value_tbl " 747*0Sstevel@tonic-gate "WHERE (value_id = '%q')", cur); 748*0Sstevel@tonic-gate 749*0Sstevel@tonic-gate switch (r = backend_tx_run(tx, q, property_value_size_cb, 750*0Sstevel@tonic-gate &info)) { 751*0Sstevel@tonic-gate case REP_PROTOCOL_SUCCESS: 752*0Sstevel@tonic-gate break; 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate case REP_PROTOCOL_FAIL_NO_RESOURCES: 755*0Sstevel@tonic-gate backend_query_free(q); 756*0Sstevel@tonic-gate return (BACKEND_CALLBACK_ABORT); 757*0Sstevel@tonic-gate 758*0Sstevel@tonic-gate case REP_PROTOCOL_DONE: 759*0Sstevel@tonic-gate default: 760*0Sstevel@tonic-gate backend_panic("backend_tx_run() returned %d", r); 761*0Sstevel@tonic-gate } 762*0Sstevel@tonic-gate if (info.pvi_size > 0) { 763*0Sstevel@tonic-gate info.pvi_base = uu_zalloc(info.pvi_size); 764*0Sstevel@tonic-gate if (info.pvi_base == NULL) { 765*0Sstevel@tonic-gate backend_query_free(q); 766*0Sstevel@tonic-gate return (BACKEND_CALLBACK_ABORT); 767*0Sstevel@tonic-gate } 768*0Sstevel@tonic-gate switch (r = backend_tx_run(tx, q, property_value_cb, 769*0Sstevel@tonic-gate &info)) { 770*0Sstevel@tonic-gate case REP_PROTOCOL_SUCCESS: 771*0Sstevel@tonic-gate break; 772*0Sstevel@tonic-gate 773*0Sstevel@tonic-gate case REP_PROTOCOL_FAIL_NO_RESOURCES: 774*0Sstevel@tonic-gate uu_free(info.pvi_base); 775*0Sstevel@tonic-gate backend_query_free(q); 776*0Sstevel@tonic-gate return (BACKEND_CALLBACK_ABORT); 777*0Sstevel@tonic-gate 778*0Sstevel@tonic-gate case REP_PROTOCOL_DONE: 779*0Sstevel@tonic-gate default: 780*0Sstevel@tonic-gate backend_panic("backend_tx_run() returned %d", 781*0Sstevel@tonic-gate r); 782*0Sstevel@tonic-gate } 783*0Sstevel@tonic-gate } 784*0Sstevel@tonic-gate backend_query_free(q); 785*0Sstevel@tonic-gate } 786*0Sstevel@tonic-gate 787*0Sstevel@tonic-gate rc = rc_node_create_property(cp->ci_parent, lp, name, type, 788*0Sstevel@tonic-gate info.pvi_base, info.pvi_count, info.pvi_size); 789*0Sstevel@tonic-gate if (rc != REP_PROTOCOL_SUCCESS) { 790*0Sstevel@tonic-gate assert(rc == REP_PROTOCOL_FAIL_NO_RESOURCES); 791*0Sstevel@tonic-gate return (BACKEND_CALLBACK_ABORT); 792*0Sstevel@tonic-gate } 793*0Sstevel@tonic-gate 794*0Sstevel@tonic-gate return (BACKEND_CALLBACK_CONTINUE); 795*0Sstevel@tonic-gate } 796*0Sstevel@tonic-gate 797*0Sstevel@tonic-gate /* 798*0Sstevel@tonic-gate * The *_setup_child_info() functions fill in a child_info_t structure with the 799*0Sstevel@tonic-gate * information for the children of np with type type. 800*0Sstevel@tonic-gate * 801*0Sstevel@tonic-gate * They fail with 802*0Sstevel@tonic-gate * _TYPE_MISMATCH - object cannot have children of type type 803*0Sstevel@tonic-gate */ 804*0Sstevel@tonic-gate 805*0Sstevel@tonic-gate static int 806*0Sstevel@tonic-gate scope_setup_child_info(rc_node_t *np, uint32_t type, child_info_t *cip) 807*0Sstevel@tonic-gate { 808*0Sstevel@tonic-gate if (type != REP_PROTOCOL_ENTITY_SERVICE) 809*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_TYPE_MISMATCH); 810*0Sstevel@tonic-gate 811*0Sstevel@tonic-gate bzero(cip, sizeof (*cip)); 812*0Sstevel@tonic-gate cip->ci_parent = np; 813*0Sstevel@tonic-gate cip->ci_base_nl.rl_type = type; 814*0Sstevel@tonic-gate cip->ci_base_nl.rl_backend = np->rn_id.rl_backend; 815*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 816*0Sstevel@tonic-gate } 817*0Sstevel@tonic-gate 818*0Sstevel@tonic-gate static int 819*0Sstevel@tonic-gate service_setup_child_info(rc_node_t *np, uint32_t type, child_info_t *cip) 820*0Sstevel@tonic-gate { 821*0Sstevel@tonic-gate switch (type) { 822*0Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_INSTANCE: 823*0Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_PROPERTYGRP: 824*0Sstevel@tonic-gate break; 825*0Sstevel@tonic-gate default: 826*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_TYPE_MISMATCH); 827*0Sstevel@tonic-gate } 828*0Sstevel@tonic-gate 829*0Sstevel@tonic-gate bzero(cip, sizeof (*cip)); 830*0Sstevel@tonic-gate cip->ci_parent = np; 831*0Sstevel@tonic-gate cip->ci_base_nl.rl_type = type; 832*0Sstevel@tonic-gate cip->ci_base_nl.rl_backend = np->rn_id.rl_backend; 833*0Sstevel@tonic-gate cip->ci_base_nl.rl_ids[ID_SERVICE] = np->rn_id.rl_main_id; 834*0Sstevel@tonic-gate 835*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 836*0Sstevel@tonic-gate } 837*0Sstevel@tonic-gate 838*0Sstevel@tonic-gate static int 839*0Sstevel@tonic-gate instance_setup_child_info(rc_node_t *np, uint32_t type, child_info_t *cip) 840*0Sstevel@tonic-gate { 841*0Sstevel@tonic-gate switch (type) { 842*0Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_PROPERTYGRP: 843*0Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_SNAPSHOT: 844*0Sstevel@tonic-gate break; 845*0Sstevel@tonic-gate default: 846*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_TYPE_MISMATCH); 847*0Sstevel@tonic-gate } 848*0Sstevel@tonic-gate 849*0Sstevel@tonic-gate bzero(cip, sizeof (*cip)); 850*0Sstevel@tonic-gate cip->ci_parent = np; 851*0Sstevel@tonic-gate cip->ci_base_nl.rl_type = type; 852*0Sstevel@tonic-gate cip->ci_base_nl.rl_backend = np->rn_id.rl_backend; 853*0Sstevel@tonic-gate cip->ci_base_nl.rl_ids[ID_SERVICE] = np->rn_id.rl_ids[ID_SERVICE]; 854*0Sstevel@tonic-gate cip->ci_base_nl.rl_ids[ID_INSTANCE] = np->rn_id.rl_main_id; 855*0Sstevel@tonic-gate 856*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 857*0Sstevel@tonic-gate } 858*0Sstevel@tonic-gate 859*0Sstevel@tonic-gate static int 860*0Sstevel@tonic-gate snaplevel_setup_child_info(rc_node_t *np, uint32_t type, child_info_t *cip) 861*0Sstevel@tonic-gate { 862*0Sstevel@tonic-gate if (type != REP_PROTOCOL_ENTITY_PROPERTYGRP) 863*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_TYPE_MISMATCH); 864*0Sstevel@tonic-gate 865*0Sstevel@tonic-gate bzero(cip, sizeof (*cip)); 866*0Sstevel@tonic-gate cip->ci_parent = np; 867*0Sstevel@tonic-gate cip->ci_base_nl.rl_type = type; 868*0Sstevel@tonic-gate cip->ci_base_nl.rl_backend = np->rn_id.rl_backend; 869*0Sstevel@tonic-gate cip->ci_base_nl.rl_ids[ID_SERVICE] = np->rn_id.rl_ids[ID_SERVICE]; 870*0Sstevel@tonic-gate cip->ci_base_nl.rl_ids[ID_INSTANCE] = np->rn_id.rl_ids[ID_INSTANCE]; 871*0Sstevel@tonic-gate cip->ci_base_nl.rl_ids[ID_NAME] = np->rn_id.rl_ids[ID_NAME]; 872*0Sstevel@tonic-gate cip->ci_base_nl.rl_ids[ID_SNAPSHOT] = np->rn_id.rl_ids[ID_SNAPSHOT]; 873*0Sstevel@tonic-gate cip->ci_base_nl.rl_ids[ID_LEVEL] = np->rn_id.rl_main_id; 874*0Sstevel@tonic-gate 875*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 876*0Sstevel@tonic-gate } 877*0Sstevel@tonic-gate 878*0Sstevel@tonic-gate static int 879*0Sstevel@tonic-gate propertygrp_setup_child_info(rc_node_t *pg, uint32_t type, child_info_t *cip) 880*0Sstevel@tonic-gate { 881*0Sstevel@tonic-gate if (type != REP_PROTOCOL_ENTITY_PROPERTY) 882*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_TYPE_MISMATCH); 883*0Sstevel@tonic-gate 884*0Sstevel@tonic-gate bzero(cip, sizeof (*cip)); 885*0Sstevel@tonic-gate cip->ci_parent = pg; 886*0Sstevel@tonic-gate cip->ci_base_nl.rl_type = type; 887*0Sstevel@tonic-gate cip->ci_base_nl.rl_backend = pg->rn_id.rl_backend; 888*0Sstevel@tonic-gate cip->ci_base_nl.rl_ids[ID_SERVICE] = pg->rn_id.rl_ids[ID_SERVICE]; 889*0Sstevel@tonic-gate cip->ci_base_nl.rl_ids[ID_INSTANCE] = pg->rn_id.rl_ids[ID_INSTANCE]; 890*0Sstevel@tonic-gate cip->ci_base_nl.rl_ids[ID_PG] = pg->rn_id.rl_main_id; 891*0Sstevel@tonic-gate cip->ci_base_nl.rl_ids[ID_GEN] = pg->rn_gen_id; 892*0Sstevel@tonic-gate cip->ci_base_nl.rl_ids[ID_NAME] = pg->rn_id.rl_ids[ID_NAME]; 893*0Sstevel@tonic-gate cip->ci_base_nl.rl_ids[ID_SNAPSHOT] = pg->rn_id.rl_ids[ID_SNAPSHOT]; 894*0Sstevel@tonic-gate cip->ci_base_nl.rl_ids[ID_LEVEL] = pg->rn_id.rl_ids[ID_LEVEL]; 895*0Sstevel@tonic-gate 896*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 897*0Sstevel@tonic-gate } 898*0Sstevel@tonic-gate 899*0Sstevel@tonic-gate /* 900*0Sstevel@tonic-gate * The *_fill_children() functions populate the children of the given rc_node_t 901*0Sstevel@tonic-gate * by querying the database and calling rc_node_setup_*() functions (usually 902*0Sstevel@tonic-gate * via a fill_*_callback()). 903*0Sstevel@tonic-gate * 904*0Sstevel@tonic-gate * They fail with 905*0Sstevel@tonic-gate * _NO_RESOURCES 906*0Sstevel@tonic-gate */ 907*0Sstevel@tonic-gate 908*0Sstevel@tonic-gate /* 909*0Sstevel@tonic-gate * Returns 910*0Sstevel@tonic-gate * _NO_RESOURCES 911*0Sstevel@tonic-gate * _SUCCESS 912*0Sstevel@tonic-gate */ 913*0Sstevel@tonic-gate static int 914*0Sstevel@tonic-gate scope_fill_children(rc_node_t *np) 915*0Sstevel@tonic-gate { 916*0Sstevel@tonic-gate backend_query_t *q; 917*0Sstevel@tonic-gate child_info_t ci; 918*0Sstevel@tonic-gate int res; 919*0Sstevel@tonic-gate 920*0Sstevel@tonic-gate (void) scope_setup_child_info(np, REP_PROTOCOL_ENTITY_SERVICE, &ci); 921*0Sstevel@tonic-gate 922*0Sstevel@tonic-gate q = backend_query_alloc(); 923*0Sstevel@tonic-gate backend_query_append(q, "SELECT svc_name, svc_id FROM service_tbl"); 924*0Sstevel@tonic-gate res = backend_run(BACKEND_TYPE_NORMAL, q, fill_child_callback, &ci); 925*0Sstevel@tonic-gate backend_query_free(q); 926*0Sstevel@tonic-gate 927*0Sstevel@tonic-gate if (res == REP_PROTOCOL_DONE) 928*0Sstevel@tonic-gate res = REP_PROTOCOL_FAIL_NO_RESOURCES; 929*0Sstevel@tonic-gate return (res); 930*0Sstevel@tonic-gate } 931*0Sstevel@tonic-gate 932*0Sstevel@tonic-gate /* 933*0Sstevel@tonic-gate * Returns 934*0Sstevel@tonic-gate * _NO_RESOURCES 935*0Sstevel@tonic-gate * _SUCCESS 936*0Sstevel@tonic-gate */ 937*0Sstevel@tonic-gate static int 938*0Sstevel@tonic-gate service_fill_children(rc_node_t *np) 939*0Sstevel@tonic-gate { 940*0Sstevel@tonic-gate backend_query_t *q; 941*0Sstevel@tonic-gate child_info_t ci; 942*0Sstevel@tonic-gate int res; 943*0Sstevel@tonic-gate 944*0Sstevel@tonic-gate assert(np->rn_id.rl_backend == BACKEND_TYPE_NORMAL); 945*0Sstevel@tonic-gate 946*0Sstevel@tonic-gate (void) service_setup_child_info(np, REP_PROTOCOL_ENTITY_INSTANCE, &ci); 947*0Sstevel@tonic-gate 948*0Sstevel@tonic-gate q = backend_query_alloc(); 949*0Sstevel@tonic-gate backend_query_add(q, 950*0Sstevel@tonic-gate "SELECT instance_name, instance_id FROM instance_tbl" 951*0Sstevel@tonic-gate " WHERE (instance_svc = %d)", 952*0Sstevel@tonic-gate np->rn_id.rl_main_id); 953*0Sstevel@tonic-gate res = backend_run(BACKEND_TYPE_NORMAL, q, fill_child_callback, &ci); 954*0Sstevel@tonic-gate backend_query_free(q); 955*0Sstevel@tonic-gate 956*0Sstevel@tonic-gate if (res == REP_PROTOCOL_DONE) 957*0Sstevel@tonic-gate res = REP_PROTOCOL_FAIL_NO_RESOURCES; 958*0Sstevel@tonic-gate if (res != REP_PROTOCOL_SUCCESS) 959*0Sstevel@tonic-gate return (res); 960*0Sstevel@tonic-gate 961*0Sstevel@tonic-gate (void) service_setup_child_info(np, REP_PROTOCOL_ENTITY_PROPERTYGRP, 962*0Sstevel@tonic-gate &ci); 963*0Sstevel@tonic-gate 964*0Sstevel@tonic-gate q = backend_query_alloc(); 965*0Sstevel@tonic-gate backend_query_add(q, 966*0Sstevel@tonic-gate "SELECT pg_name, pg_id, pg_gen_id, pg_type, pg_flags FROM pg_tbl" 967*0Sstevel@tonic-gate " WHERE (pg_parent_id = %d)", 968*0Sstevel@tonic-gate np->rn_id.rl_main_id); 969*0Sstevel@tonic-gate 970*0Sstevel@tonic-gate ci.ci_base_nl.rl_backend = BACKEND_TYPE_NORMAL; 971*0Sstevel@tonic-gate res = backend_run(BACKEND_TYPE_NORMAL, q, fill_pg_callback, &ci); 972*0Sstevel@tonic-gate if (res == REP_PROTOCOL_SUCCESS) { 973*0Sstevel@tonic-gate ci.ci_base_nl.rl_backend = BACKEND_TYPE_NONPERSIST; 974*0Sstevel@tonic-gate res = backend_run(BACKEND_TYPE_NONPERSIST, q, 975*0Sstevel@tonic-gate fill_pg_callback, &ci); 976*0Sstevel@tonic-gate /* nonpersistant database may not exist */ 977*0Sstevel@tonic-gate if (res == REP_PROTOCOL_FAIL_BACKEND_ACCESS) 978*0Sstevel@tonic-gate res = REP_PROTOCOL_SUCCESS; 979*0Sstevel@tonic-gate } 980*0Sstevel@tonic-gate if (res == REP_PROTOCOL_DONE) 981*0Sstevel@tonic-gate res = REP_PROTOCOL_FAIL_NO_RESOURCES; 982*0Sstevel@tonic-gate backend_query_free(q); 983*0Sstevel@tonic-gate 984*0Sstevel@tonic-gate return (res); 985*0Sstevel@tonic-gate } 986*0Sstevel@tonic-gate 987*0Sstevel@tonic-gate /* 988*0Sstevel@tonic-gate * Returns 989*0Sstevel@tonic-gate * _NO_RESOURCES 990*0Sstevel@tonic-gate * _SUCCESS 991*0Sstevel@tonic-gate */ 992*0Sstevel@tonic-gate static int 993*0Sstevel@tonic-gate instance_fill_children(rc_node_t *np) 994*0Sstevel@tonic-gate { 995*0Sstevel@tonic-gate backend_query_t *q; 996*0Sstevel@tonic-gate child_info_t ci; 997*0Sstevel@tonic-gate int res; 998*0Sstevel@tonic-gate 999*0Sstevel@tonic-gate assert(np->rn_id.rl_backend == BACKEND_TYPE_NORMAL); 1000*0Sstevel@tonic-gate 1001*0Sstevel@tonic-gate /* Get child property groups */ 1002*0Sstevel@tonic-gate (void) instance_setup_child_info(np, REP_PROTOCOL_ENTITY_PROPERTYGRP, 1003*0Sstevel@tonic-gate &ci); 1004*0Sstevel@tonic-gate 1005*0Sstevel@tonic-gate q = backend_query_alloc(); 1006*0Sstevel@tonic-gate backend_query_add(q, 1007*0Sstevel@tonic-gate "SELECT pg_name, pg_id, pg_gen_id, pg_type, pg_flags FROM pg_tbl" 1008*0Sstevel@tonic-gate " WHERE (pg_parent_id = %d)", 1009*0Sstevel@tonic-gate np->rn_id.rl_main_id); 1010*0Sstevel@tonic-gate ci.ci_base_nl.rl_backend = BACKEND_TYPE_NORMAL; 1011*0Sstevel@tonic-gate res = backend_run(BACKEND_TYPE_NORMAL, q, fill_pg_callback, &ci); 1012*0Sstevel@tonic-gate if (res == REP_PROTOCOL_SUCCESS) { 1013*0Sstevel@tonic-gate ci.ci_base_nl.rl_backend = BACKEND_TYPE_NONPERSIST; 1014*0Sstevel@tonic-gate res = backend_run(BACKEND_TYPE_NONPERSIST, q, 1015*0Sstevel@tonic-gate fill_pg_callback, &ci); 1016*0Sstevel@tonic-gate /* nonpersistant database may not exist */ 1017*0Sstevel@tonic-gate if (res == REP_PROTOCOL_FAIL_BACKEND_ACCESS) 1018*0Sstevel@tonic-gate res = REP_PROTOCOL_SUCCESS; 1019*0Sstevel@tonic-gate } 1020*0Sstevel@tonic-gate if (res == REP_PROTOCOL_DONE) 1021*0Sstevel@tonic-gate res = REP_PROTOCOL_FAIL_NO_RESOURCES; 1022*0Sstevel@tonic-gate backend_query_free(q); 1023*0Sstevel@tonic-gate 1024*0Sstevel@tonic-gate if (res != REP_PROTOCOL_SUCCESS) 1025*0Sstevel@tonic-gate return (res); 1026*0Sstevel@tonic-gate 1027*0Sstevel@tonic-gate /* Get child snapshots */ 1028*0Sstevel@tonic-gate (void) instance_setup_child_info(np, REP_PROTOCOL_ENTITY_SNAPSHOT, 1029*0Sstevel@tonic-gate &ci); 1030*0Sstevel@tonic-gate 1031*0Sstevel@tonic-gate q = backend_query_alloc(); 1032*0Sstevel@tonic-gate backend_query_add(q, 1033*0Sstevel@tonic-gate "SELECT lnk_snap_name, lnk_id, lnk_snap_id FROM snapshot_lnk_tbl" 1034*0Sstevel@tonic-gate " WHERE (lnk_inst_id = %d)", 1035*0Sstevel@tonic-gate np->rn_id.rl_main_id); 1036*0Sstevel@tonic-gate res = backend_run(BACKEND_TYPE_NORMAL, q, fill_snapshot_callback, &ci); 1037*0Sstevel@tonic-gate if (res == REP_PROTOCOL_DONE) 1038*0Sstevel@tonic-gate res = REP_PROTOCOL_FAIL_NO_RESOURCES; 1039*0Sstevel@tonic-gate backend_query_free(q); 1040*0Sstevel@tonic-gate 1041*0Sstevel@tonic-gate return (res); 1042*0Sstevel@tonic-gate } 1043*0Sstevel@tonic-gate 1044*0Sstevel@tonic-gate /* 1045*0Sstevel@tonic-gate * Returns 1046*0Sstevel@tonic-gate * _NO_RESOURCES 1047*0Sstevel@tonic-gate * _SUCCESS 1048*0Sstevel@tonic-gate */ 1049*0Sstevel@tonic-gate static int 1050*0Sstevel@tonic-gate snapshot_fill_children(rc_node_t *np) 1051*0Sstevel@tonic-gate { 1052*0Sstevel@tonic-gate rc_node_t *nnp; 1053*0Sstevel@tonic-gate rc_snapshot_t *sp, *oldsp; 1054*0Sstevel@tonic-gate rc_snaplevel_t *lvl; 1055*0Sstevel@tonic-gate rc_node_lookup_t nl; 1056*0Sstevel@tonic-gate int r; 1057*0Sstevel@tonic-gate 1058*0Sstevel@tonic-gate /* Get the rc_snapshot_t (& its rc_snaplevel_t's). */ 1059*0Sstevel@tonic-gate (void) pthread_mutex_lock(&np->rn_lock); 1060*0Sstevel@tonic-gate sp = np->rn_snapshot; 1061*0Sstevel@tonic-gate (void) pthread_mutex_unlock(&np->rn_lock); 1062*0Sstevel@tonic-gate if (sp == NULL) { 1063*0Sstevel@tonic-gate r = rc_snapshot_get(np->rn_snapshot_id, &sp); 1064*0Sstevel@tonic-gate if (r != REP_PROTOCOL_SUCCESS) { 1065*0Sstevel@tonic-gate assert(r == REP_PROTOCOL_FAIL_NO_RESOURCES); 1066*0Sstevel@tonic-gate return (r); 1067*0Sstevel@tonic-gate } 1068*0Sstevel@tonic-gate (void) pthread_mutex_lock(&np->rn_lock); 1069*0Sstevel@tonic-gate oldsp = np->rn_snapshot; 1070*0Sstevel@tonic-gate assert(oldsp == NULL || oldsp == sp); 1071*0Sstevel@tonic-gate np->rn_snapshot = sp; 1072*0Sstevel@tonic-gate (void) pthread_mutex_unlock(&np->rn_lock); 1073*0Sstevel@tonic-gate if (oldsp != NULL) 1074*0Sstevel@tonic-gate rc_snapshot_rele(oldsp); 1075*0Sstevel@tonic-gate } 1076*0Sstevel@tonic-gate 1077*0Sstevel@tonic-gate bzero(&nl, sizeof (nl)); 1078*0Sstevel@tonic-gate nl.rl_type = REP_PROTOCOL_ENTITY_SNAPLEVEL; 1079*0Sstevel@tonic-gate nl.rl_backend = np->rn_id.rl_backend; 1080*0Sstevel@tonic-gate nl.rl_ids[ID_SERVICE] = np->rn_id.rl_ids[ID_SERVICE]; 1081*0Sstevel@tonic-gate nl.rl_ids[ID_INSTANCE] = np->rn_id.rl_ids[ID_INSTANCE]; 1082*0Sstevel@tonic-gate nl.rl_ids[ID_NAME] = np->rn_id.rl_main_id; 1083*0Sstevel@tonic-gate nl.rl_ids[ID_SNAPSHOT] = np->rn_snapshot_id; 1084*0Sstevel@tonic-gate 1085*0Sstevel@tonic-gate /* Create rc_node_t's for the snapshot's rc_snaplevel_t's. */ 1086*0Sstevel@tonic-gate for (lvl = sp->rs_levels; lvl != NULL; lvl = lvl->rsl_next) { 1087*0Sstevel@tonic-gate nnp = rc_node_alloc(); 1088*0Sstevel@tonic-gate assert(nnp != NULL); 1089*0Sstevel@tonic-gate nl.rl_main_id = lvl->rsl_level_id; 1090*0Sstevel@tonic-gate nnp = rc_node_setup_snaplevel(nnp, &nl, lvl, np); 1091*0Sstevel@tonic-gate rc_node_rele(nnp); 1092*0Sstevel@tonic-gate } 1093*0Sstevel@tonic-gate 1094*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 1095*0Sstevel@tonic-gate } 1096*0Sstevel@tonic-gate 1097*0Sstevel@tonic-gate /* 1098*0Sstevel@tonic-gate * Returns 1099*0Sstevel@tonic-gate * _NO_RESOURCES 1100*0Sstevel@tonic-gate * _SUCCESS 1101*0Sstevel@tonic-gate */ 1102*0Sstevel@tonic-gate static int 1103*0Sstevel@tonic-gate snaplevel_fill_children(rc_node_t *np) 1104*0Sstevel@tonic-gate { 1105*0Sstevel@tonic-gate rc_snaplevel_t *lvl = np->rn_snaplevel; 1106*0Sstevel@tonic-gate child_info_t ci; 1107*0Sstevel@tonic-gate int res; 1108*0Sstevel@tonic-gate backend_query_t *q; 1109*0Sstevel@tonic-gate 1110*0Sstevel@tonic-gate (void) snaplevel_setup_child_info(np, REP_PROTOCOL_ENTITY_PROPERTYGRP, 1111*0Sstevel@tonic-gate &ci); 1112*0Sstevel@tonic-gate 1113*0Sstevel@tonic-gate q = backend_query_alloc(); 1114*0Sstevel@tonic-gate backend_query_add(q, 1115*0Sstevel@tonic-gate "SELECT snaplvl_pg_name, snaplvl_pg_id, snaplvl_gen_id, " 1116*0Sstevel@tonic-gate " snaplvl_pg_type, snaplvl_pg_flags " 1117*0Sstevel@tonic-gate " FROM snaplevel_lnk_tbl " 1118*0Sstevel@tonic-gate " WHERE (snaplvl_level_id = %d)", 1119*0Sstevel@tonic-gate lvl->rsl_level_id); 1120*0Sstevel@tonic-gate res = backend_run(BACKEND_TYPE_NORMAL, q, fill_pg_callback, &ci); 1121*0Sstevel@tonic-gate if (res == REP_PROTOCOL_DONE) 1122*0Sstevel@tonic-gate res = REP_PROTOCOL_FAIL_NO_RESOURCES; 1123*0Sstevel@tonic-gate backend_query_free(q); 1124*0Sstevel@tonic-gate 1125*0Sstevel@tonic-gate return (res); 1126*0Sstevel@tonic-gate } 1127*0Sstevel@tonic-gate 1128*0Sstevel@tonic-gate /* 1129*0Sstevel@tonic-gate * Returns 1130*0Sstevel@tonic-gate * _NO_RESOURCES 1131*0Sstevel@tonic-gate * _SUCCESS 1132*0Sstevel@tonic-gate */ 1133*0Sstevel@tonic-gate static int 1134*0Sstevel@tonic-gate propertygrp_fill_children(rc_node_t *np) 1135*0Sstevel@tonic-gate { 1136*0Sstevel@tonic-gate backend_query_t *q; 1137*0Sstevel@tonic-gate child_info_t ci; 1138*0Sstevel@tonic-gate int res; 1139*0Sstevel@tonic-gate backend_tx_t *tx; 1140*0Sstevel@tonic-gate 1141*0Sstevel@tonic-gate backend_type_t backend = np->rn_id.rl_backend; 1142*0Sstevel@tonic-gate 1143*0Sstevel@tonic-gate (void) propertygrp_setup_child_info(np, REP_PROTOCOL_ENTITY_PROPERTY, 1144*0Sstevel@tonic-gate &ci); 1145*0Sstevel@tonic-gate 1146*0Sstevel@tonic-gate res = backend_tx_begin_ro(backend, &tx); 1147*0Sstevel@tonic-gate if (res != REP_PROTOCOL_SUCCESS) { 1148*0Sstevel@tonic-gate /* 1149*0Sstevel@tonic-gate * If the backend didn't exist, we wouldn't have got this 1150*0Sstevel@tonic-gate * property group. 1151*0Sstevel@tonic-gate */ 1152*0Sstevel@tonic-gate assert(res != REP_PROTOCOL_FAIL_BACKEND_ACCESS); 1153*0Sstevel@tonic-gate return (res); 1154*0Sstevel@tonic-gate } 1155*0Sstevel@tonic-gate 1156*0Sstevel@tonic-gate ci.ci_tx = tx; 1157*0Sstevel@tonic-gate 1158*0Sstevel@tonic-gate q = backend_query_alloc(); 1159*0Sstevel@tonic-gate backend_query_add(q, 1160*0Sstevel@tonic-gate "SELECT lnk_prop_name, lnk_prop_id, lnk_prop_type, lnk_val_id " 1161*0Sstevel@tonic-gate "FROM prop_lnk_tbl " 1162*0Sstevel@tonic-gate "WHERE (lnk_pg_id = %d AND lnk_gen_id = %d)", 1163*0Sstevel@tonic-gate np->rn_id.rl_main_id, np->rn_gen_id); 1164*0Sstevel@tonic-gate res = backend_tx_run(tx, q, fill_property_callback, &ci); 1165*0Sstevel@tonic-gate if (res == REP_PROTOCOL_DONE) 1166*0Sstevel@tonic-gate res = REP_PROTOCOL_FAIL_NO_RESOURCES; 1167*0Sstevel@tonic-gate backend_query_free(q); 1168*0Sstevel@tonic-gate backend_tx_end_ro(tx); 1169*0Sstevel@tonic-gate 1170*0Sstevel@tonic-gate return (res); 1171*0Sstevel@tonic-gate } 1172*0Sstevel@tonic-gate 1173*0Sstevel@tonic-gate /* 1174*0Sstevel@tonic-gate * Fails with 1175*0Sstevel@tonic-gate * _TYPE_MISMATCH - lp is not for a service 1176*0Sstevel@tonic-gate * _INVALID_TYPE - lp has invalid type 1177*0Sstevel@tonic-gate * _BAD_REQUEST - name is invalid 1178*0Sstevel@tonic-gate */ 1179*0Sstevel@tonic-gate static int 1180*0Sstevel@tonic-gate scope_query_child(backend_query_t *q, rc_node_lookup_t *lp, const char *name) 1181*0Sstevel@tonic-gate { 1182*0Sstevel@tonic-gate uint32_t type = lp->rl_type; 1183*0Sstevel@tonic-gate int rc; 1184*0Sstevel@tonic-gate 1185*0Sstevel@tonic-gate if (type != REP_PROTOCOL_ENTITY_SERVICE) 1186*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_TYPE_MISMATCH); 1187*0Sstevel@tonic-gate 1188*0Sstevel@tonic-gate if ((rc = rc_check_type_name(type, name)) != REP_PROTOCOL_SUCCESS) 1189*0Sstevel@tonic-gate return (rc); 1190*0Sstevel@tonic-gate 1191*0Sstevel@tonic-gate backend_query_add(q, 1192*0Sstevel@tonic-gate "SELECT svc_id FROM service_tbl " 1193*0Sstevel@tonic-gate "WHERE svc_name = '%q'", 1194*0Sstevel@tonic-gate name); 1195*0Sstevel@tonic-gate 1196*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 1197*0Sstevel@tonic-gate } 1198*0Sstevel@tonic-gate 1199*0Sstevel@tonic-gate /* 1200*0Sstevel@tonic-gate * Fails with 1201*0Sstevel@tonic-gate * _NO_RESOURCES - out of memory 1202*0Sstevel@tonic-gate */ 1203*0Sstevel@tonic-gate static int 1204*0Sstevel@tonic-gate scope_insert_child(backend_tx_t *tx, rc_node_lookup_t *lp, const char *name) 1205*0Sstevel@tonic-gate { 1206*0Sstevel@tonic-gate return (backend_tx_run_update(tx, 1207*0Sstevel@tonic-gate "INSERT INTO service_tbl (svc_id, svc_name) " 1208*0Sstevel@tonic-gate "VALUES (%d, '%q')", 1209*0Sstevel@tonic-gate lp->rl_main_id, name)); 1210*0Sstevel@tonic-gate } 1211*0Sstevel@tonic-gate 1212*0Sstevel@tonic-gate /* 1213*0Sstevel@tonic-gate * Fails with 1214*0Sstevel@tonic-gate * _TYPE_MISMATCH - lp is not for an instance or property group 1215*0Sstevel@tonic-gate * _INVALID_TYPE - lp has invalid type 1216*0Sstevel@tonic-gate * _BAD_REQUEST - name is invalid 1217*0Sstevel@tonic-gate */ 1218*0Sstevel@tonic-gate static int 1219*0Sstevel@tonic-gate service_query_child(backend_query_t *q, rc_node_lookup_t *lp, const char *name) 1220*0Sstevel@tonic-gate { 1221*0Sstevel@tonic-gate uint32_t type = lp->rl_type; 1222*0Sstevel@tonic-gate int rc; 1223*0Sstevel@tonic-gate 1224*0Sstevel@tonic-gate if (type != REP_PROTOCOL_ENTITY_INSTANCE && 1225*0Sstevel@tonic-gate type != REP_PROTOCOL_ENTITY_PROPERTYGRP) 1226*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_TYPE_MISMATCH); 1227*0Sstevel@tonic-gate 1228*0Sstevel@tonic-gate if ((rc = rc_check_type_name(type, name)) != REP_PROTOCOL_SUCCESS) 1229*0Sstevel@tonic-gate return (rc); 1230*0Sstevel@tonic-gate 1231*0Sstevel@tonic-gate switch (type) { 1232*0Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_INSTANCE: 1233*0Sstevel@tonic-gate backend_query_add(q, 1234*0Sstevel@tonic-gate "SELECT instance_id FROM instance_tbl " 1235*0Sstevel@tonic-gate "WHERE instance_name = '%q' AND instance_svc = %d", 1236*0Sstevel@tonic-gate name, lp->rl_ids[ID_SERVICE]); 1237*0Sstevel@tonic-gate break; 1238*0Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_PROPERTYGRP: 1239*0Sstevel@tonic-gate backend_query_add(q, 1240*0Sstevel@tonic-gate "SELECT pg_id FROM pg_tbl " 1241*0Sstevel@tonic-gate " WHERE pg_name = '%q' AND pg_parent_id = %d", 1242*0Sstevel@tonic-gate name, lp->rl_ids[ID_SERVICE]); 1243*0Sstevel@tonic-gate break; 1244*0Sstevel@tonic-gate default: 1245*0Sstevel@tonic-gate assert(0); 1246*0Sstevel@tonic-gate abort(); 1247*0Sstevel@tonic-gate } 1248*0Sstevel@tonic-gate 1249*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 1250*0Sstevel@tonic-gate } 1251*0Sstevel@tonic-gate 1252*0Sstevel@tonic-gate /* 1253*0Sstevel@tonic-gate * Fails with 1254*0Sstevel@tonic-gate * _NO_RESOURCES - out of memory 1255*0Sstevel@tonic-gate */ 1256*0Sstevel@tonic-gate static int 1257*0Sstevel@tonic-gate service_insert_child(backend_tx_t *tx, rc_node_lookup_t *lp, const char *name) 1258*0Sstevel@tonic-gate { 1259*0Sstevel@tonic-gate return (backend_tx_run_update(tx, 1260*0Sstevel@tonic-gate "INSERT INTO instance_tbl " 1261*0Sstevel@tonic-gate " (instance_id, instance_name, instance_svc) " 1262*0Sstevel@tonic-gate "VALUES (%d, '%q', %d)", 1263*0Sstevel@tonic-gate lp->rl_main_id, name, lp->rl_ids[ID_SERVICE])); 1264*0Sstevel@tonic-gate } 1265*0Sstevel@tonic-gate 1266*0Sstevel@tonic-gate /* 1267*0Sstevel@tonic-gate * Fails with 1268*0Sstevel@tonic-gate * _NO_RESOURCES - out of memory 1269*0Sstevel@tonic-gate */ 1270*0Sstevel@tonic-gate static int 1271*0Sstevel@tonic-gate instance_insert_child(backend_tx_t *tx, rc_node_lookup_t *lp, const char *name) 1272*0Sstevel@tonic-gate { 1273*0Sstevel@tonic-gate return (backend_tx_run_update(tx, 1274*0Sstevel@tonic-gate "INSERT INTO snapshot_lnk_tbl " 1275*0Sstevel@tonic-gate " (lnk_id, lnk_inst_id, lnk_snap_name, lnk_snap_id) " 1276*0Sstevel@tonic-gate "VALUES (%d, %d, '%q', 0)", 1277*0Sstevel@tonic-gate lp->rl_main_id, lp->rl_ids[ID_INSTANCE], name)); 1278*0Sstevel@tonic-gate } 1279*0Sstevel@tonic-gate 1280*0Sstevel@tonic-gate /* 1281*0Sstevel@tonic-gate * Fails with 1282*0Sstevel@tonic-gate * _TYPE_MISMATCH - lp is not for a property group or snapshot 1283*0Sstevel@tonic-gate * _INVALID_TYPE - lp has invalid type 1284*0Sstevel@tonic-gate * _BAD_REQUEST - name is invalid 1285*0Sstevel@tonic-gate */ 1286*0Sstevel@tonic-gate static int 1287*0Sstevel@tonic-gate instance_query_child(backend_query_t *q, rc_node_lookup_t *lp, const char *name) 1288*0Sstevel@tonic-gate { 1289*0Sstevel@tonic-gate uint32_t type = lp->rl_type; 1290*0Sstevel@tonic-gate int rc; 1291*0Sstevel@tonic-gate 1292*0Sstevel@tonic-gate if (type != REP_PROTOCOL_ENTITY_PROPERTYGRP && 1293*0Sstevel@tonic-gate type != REP_PROTOCOL_ENTITY_SNAPSHOT) 1294*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_TYPE_MISMATCH); 1295*0Sstevel@tonic-gate 1296*0Sstevel@tonic-gate if ((rc = rc_check_type_name(type, name)) != REP_PROTOCOL_SUCCESS) 1297*0Sstevel@tonic-gate return (rc); 1298*0Sstevel@tonic-gate 1299*0Sstevel@tonic-gate switch (type) { 1300*0Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_PROPERTYGRP: 1301*0Sstevel@tonic-gate backend_query_add(q, 1302*0Sstevel@tonic-gate "SELECT pg_id FROM pg_tbl " 1303*0Sstevel@tonic-gate " WHERE pg_name = '%q' AND pg_parent_id = %d", 1304*0Sstevel@tonic-gate name, lp->rl_ids[ID_INSTANCE]); 1305*0Sstevel@tonic-gate break; 1306*0Sstevel@tonic-gate case REP_PROTOCOL_ENTITY_SNAPSHOT: 1307*0Sstevel@tonic-gate backend_query_add(q, 1308*0Sstevel@tonic-gate "SELECT lnk_id FROM snapshot_lnk_tbl " 1309*0Sstevel@tonic-gate " WHERE lnk_snap_name = '%q' AND lnk_inst_id = %d", 1310*0Sstevel@tonic-gate name, lp->rl_ids[ID_INSTANCE]); 1311*0Sstevel@tonic-gate break; 1312*0Sstevel@tonic-gate default: 1313*0Sstevel@tonic-gate assert(0); 1314*0Sstevel@tonic-gate abort(); 1315*0Sstevel@tonic-gate } 1316*0Sstevel@tonic-gate 1317*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 1318*0Sstevel@tonic-gate } 1319*0Sstevel@tonic-gate 1320*0Sstevel@tonic-gate static int 1321*0Sstevel@tonic-gate generic_insert_pg_child(backend_tx_t *tx, rc_node_lookup_t *lp, 1322*0Sstevel@tonic-gate const char *name, const char *pgtype, uint32_t flags, uint32_t gen) 1323*0Sstevel@tonic-gate { 1324*0Sstevel@tonic-gate int parent_id = (lp->rl_ids[ID_INSTANCE] != 0)? 1325*0Sstevel@tonic-gate lp->rl_ids[ID_INSTANCE] : lp->rl_ids[ID_SERVICE]; 1326*0Sstevel@tonic-gate return (backend_tx_run_update(tx, 1327*0Sstevel@tonic-gate "INSERT INTO pg_tbl " 1328*0Sstevel@tonic-gate " (pg_id, pg_name, pg_parent_id, pg_type, pg_flags, pg_gen_id) " 1329*0Sstevel@tonic-gate "VALUES (%d, '%q', %d, '%q', %d, %d)", 1330*0Sstevel@tonic-gate lp->rl_main_id, name, parent_id, pgtype, flags, gen)); 1331*0Sstevel@tonic-gate } 1332*0Sstevel@tonic-gate 1333*0Sstevel@tonic-gate static int 1334*0Sstevel@tonic-gate service_delete_start(rc_node_t *np, delete_info_t *dip) 1335*0Sstevel@tonic-gate { 1336*0Sstevel@tonic-gate int r; 1337*0Sstevel@tonic-gate backend_query_t *q = backend_query_alloc(); 1338*0Sstevel@tonic-gate 1339*0Sstevel@tonic-gate /* 1340*0Sstevel@tonic-gate * Check for child instances, and refuse to delete if they exist. 1341*0Sstevel@tonic-gate */ 1342*0Sstevel@tonic-gate backend_query_add(q, 1343*0Sstevel@tonic-gate "SELECT 1 FROM instance_tbl WHERE instance_svc = %d", 1344*0Sstevel@tonic-gate np->rn_id.rl_main_id); 1345*0Sstevel@tonic-gate 1346*0Sstevel@tonic-gate r = backend_tx_run(dip->di_tx, q, backend_fail_if_seen, NULL); 1347*0Sstevel@tonic-gate backend_query_free(q); 1348*0Sstevel@tonic-gate 1349*0Sstevel@tonic-gate if (r == REP_PROTOCOL_DONE) 1350*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_EXISTS); /* instances exist */ 1351*0Sstevel@tonic-gate 1352*0Sstevel@tonic-gate return (delete_stack_push(dip, BACKEND_TYPE_NORMAL, &service_delete, 1353*0Sstevel@tonic-gate np->rn_id.rl_main_id, 0)); 1354*0Sstevel@tonic-gate } 1355*0Sstevel@tonic-gate 1356*0Sstevel@tonic-gate static int 1357*0Sstevel@tonic-gate instance_delete_start(rc_node_t *np, delete_info_t *dip) 1358*0Sstevel@tonic-gate { 1359*0Sstevel@tonic-gate return (delete_stack_push(dip, BACKEND_TYPE_NORMAL, &instance_delete, 1360*0Sstevel@tonic-gate np->rn_id.rl_main_id, 0)); 1361*0Sstevel@tonic-gate } 1362*0Sstevel@tonic-gate 1363*0Sstevel@tonic-gate static int 1364*0Sstevel@tonic-gate snapshot_delete_start(rc_node_t *np, delete_info_t *dip) 1365*0Sstevel@tonic-gate { 1366*0Sstevel@tonic-gate return (delete_stack_push(dip, BACKEND_TYPE_NORMAL, 1367*0Sstevel@tonic-gate &snapshot_lnk_delete, np->rn_id.rl_main_id, 0)); 1368*0Sstevel@tonic-gate } 1369*0Sstevel@tonic-gate 1370*0Sstevel@tonic-gate static int 1371*0Sstevel@tonic-gate propertygrp_delete_start(rc_node_t *np, delete_info_t *dip) 1372*0Sstevel@tonic-gate { 1373*0Sstevel@tonic-gate return (delete_stack_push(dip, np->rn_id.rl_backend, 1374*0Sstevel@tonic-gate &propertygrp_delete, np->rn_id.rl_main_id, 0)); 1375*0Sstevel@tonic-gate } 1376*0Sstevel@tonic-gate 1377*0Sstevel@tonic-gate static object_info_t info[] = { 1378*0Sstevel@tonic-gate {REP_PROTOCOL_ENTITY_NONE}, 1379*0Sstevel@tonic-gate {REP_PROTOCOL_ENTITY_SCOPE, 1380*0Sstevel@tonic-gate BACKEND_ID_INVALID, 1381*0Sstevel@tonic-gate scope_fill_children, 1382*0Sstevel@tonic-gate scope_setup_child_info, 1383*0Sstevel@tonic-gate scope_query_child, 1384*0Sstevel@tonic-gate scope_insert_child, 1385*0Sstevel@tonic-gate NULL, 1386*0Sstevel@tonic-gate NULL, 1387*0Sstevel@tonic-gate }, 1388*0Sstevel@tonic-gate {REP_PROTOCOL_ENTITY_SERVICE, 1389*0Sstevel@tonic-gate BACKEND_ID_SERVICE_INSTANCE, 1390*0Sstevel@tonic-gate service_fill_children, 1391*0Sstevel@tonic-gate service_setup_child_info, 1392*0Sstevel@tonic-gate service_query_child, 1393*0Sstevel@tonic-gate service_insert_child, 1394*0Sstevel@tonic-gate generic_insert_pg_child, 1395*0Sstevel@tonic-gate service_delete_start, 1396*0Sstevel@tonic-gate }, 1397*0Sstevel@tonic-gate {REP_PROTOCOL_ENTITY_INSTANCE, 1398*0Sstevel@tonic-gate BACKEND_ID_SERVICE_INSTANCE, 1399*0Sstevel@tonic-gate instance_fill_children, 1400*0Sstevel@tonic-gate instance_setup_child_info, 1401*0Sstevel@tonic-gate instance_query_child, 1402*0Sstevel@tonic-gate instance_insert_child, 1403*0Sstevel@tonic-gate generic_insert_pg_child, 1404*0Sstevel@tonic-gate instance_delete_start, 1405*0Sstevel@tonic-gate }, 1406*0Sstevel@tonic-gate {REP_PROTOCOL_ENTITY_SNAPSHOT, 1407*0Sstevel@tonic-gate BACKEND_ID_SNAPNAME, 1408*0Sstevel@tonic-gate snapshot_fill_children, 1409*0Sstevel@tonic-gate NULL, 1410*0Sstevel@tonic-gate NULL, 1411*0Sstevel@tonic-gate NULL, 1412*0Sstevel@tonic-gate NULL, 1413*0Sstevel@tonic-gate snapshot_delete_start, 1414*0Sstevel@tonic-gate }, 1415*0Sstevel@tonic-gate {REP_PROTOCOL_ENTITY_SNAPLEVEL, 1416*0Sstevel@tonic-gate BACKEND_ID_SNAPLEVEL, 1417*0Sstevel@tonic-gate snaplevel_fill_children, 1418*0Sstevel@tonic-gate snaplevel_setup_child_info, 1419*0Sstevel@tonic-gate }, 1420*0Sstevel@tonic-gate {REP_PROTOCOL_ENTITY_PROPERTYGRP, 1421*0Sstevel@tonic-gate BACKEND_ID_PROPERTYGRP, 1422*0Sstevel@tonic-gate propertygrp_fill_children, 1423*0Sstevel@tonic-gate NULL, 1424*0Sstevel@tonic-gate NULL, 1425*0Sstevel@tonic-gate NULL, 1426*0Sstevel@tonic-gate NULL, 1427*0Sstevel@tonic-gate propertygrp_delete_start, 1428*0Sstevel@tonic-gate }, 1429*0Sstevel@tonic-gate {REP_PROTOCOL_ENTITY_PROPERTY}, 1430*0Sstevel@tonic-gate {-1UL} 1431*0Sstevel@tonic-gate }; 1432*0Sstevel@tonic-gate #define NUM_INFO (sizeof (info) / sizeof (*info)) 1433*0Sstevel@tonic-gate 1434*0Sstevel@tonic-gate /* 1435*0Sstevel@tonic-gate * object_fill_children() populates the child list of an rc_node_t by calling 1436*0Sstevel@tonic-gate * the appropriate <type>_fill_children() which runs backend queries that 1437*0Sstevel@tonic-gate * call an appropriate fill_*_callback() which takes a row of results, 1438*0Sstevel@tonic-gate * decodes them, and calls an rc_node_setup*() function in rc_node.c to create 1439*0Sstevel@tonic-gate * a child. 1440*0Sstevel@tonic-gate * 1441*0Sstevel@tonic-gate * Fails with 1442*0Sstevel@tonic-gate * _NO_RESOURCES 1443*0Sstevel@tonic-gate */ 1444*0Sstevel@tonic-gate int 1445*0Sstevel@tonic-gate object_fill_children(rc_node_t *pp) 1446*0Sstevel@tonic-gate { 1447*0Sstevel@tonic-gate uint32_t type = pp->rn_id.rl_type; 1448*0Sstevel@tonic-gate assert(type > 0 && type < NUM_INFO); 1449*0Sstevel@tonic-gate 1450*0Sstevel@tonic-gate return ((*info[type].obj_fill_children)(pp)); 1451*0Sstevel@tonic-gate } 1452*0Sstevel@tonic-gate 1453*0Sstevel@tonic-gate int 1454*0Sstevel@tonic-gate object_delete(rc_node_t *pp) 1455*0Sstevel@tonic-gate { 1456*0Sstevel@tonic-gate int rc; 1457*0Sstevel@tonic-gate 1458*0Sstevel@tonic-gate delete_info_t dip; 1459*0Sstevel@tonic-gate delete_ent_t de; 1460*0Sstevel@tonic-gate 1461*0Sstevel@tonic-gate uint32_t type = pp->rn_id.rl_type; 1462*0Sstevel@tonic-gate assert(type > 0 && type < NUM_INFO); 1463*0Sstevel@tonic-gate 1464*0Sstevel@tonic-gate if (info[type].obj_delete_start == NULL) 1465*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_BAD_REQUEST); 1466*0Sstevel@tonic-gate 1467*0Sstevel@tonic-gate (void) memset(&dip, '\0', sizeof (dip)); 1468*0Sstevel@tonic-gate rc = backend_tx_begin(BACKEND_TYPE_NORMAL, &dip.di_tx); 1469*0Sstevel@tonic-gate if (rc != REP_PROTOCOL_SUCCESS) 1470*0Sstevel@tonic-gate return (rc); 1471*0Sstevel@tonic-gate 1472*0Sstevel@tonic-gate rc = backend_tx_begin(BACKEND_TYPE_NONPERSIST, &dip.di_np_tx); 1473*0Sstevel@tonic-gate if (rc == REP_PROTOCOL_FAIL_BACKEND_ACCESS || 1474*0Sstevel@tonic-gate rc == REP_PROTOCOL_FAIL_BACKEND_READONLY) 1475*0Sstevel@tonic-gate dip.di_np_tx = NULL; 1476*0Sstevel@tonic-gate else if (rc != REP_PROTOCOL_SUCCESS) { 1477*0Sstevel@tonic-gate backend_tx_rollback(dip.di_tx); 1478*0Sstevel@tonic-gate return (rc); 1479*0Sstevel@tonic-gate } 1480*0Sstevel@tonic-gate 1481*0Sstevel@tonic-gate if ((rc = (*info[type].obj_delete_start)(pp, &dip)) != 1482*0Sstevel@tonic-gate REP_PROTOCOL_SUCCESS) { 1483*0Sstevel@tonic-gate goto fail; 1484*0Sstevel@tonic-gate } 1485*0Sstevel@tonic-gate 1486*0Sstevel@tonic-gate while (delete_stack_pop(&dip, &de)) { 1487*0Sstevel@tonic-gate rc = (*de.de_cb)(&dip, &de); 1488*0Sstevel@tonic-gate if (rc != REP_PROTOCOL_SUCCESS) 1489*0Sstevel@tonic-gate goto fail; 1490*0Sstevel@tonic-gate } 1491*0Sstevel@tonic-gate 1492*0Sstevel@tonic-gate rc = backend_tx_commit(dip.di_tx); 1493*0Sstevel@tonic-gate if (rc != REP_PROTOCOL_SUCCESS) 1494*0Sstevel@tonic-gate backend_tx_rollback(dip.di_np_tx); 1495*0Sstevel@tonic-gate else if (dip.di_np_tx) 1496*0Sstevel@tonic-gate (void) backend_tx_commit(dip.di_np_tx); 1497*0Sstevel@tonic-gate 1498*0Sstevel@tonic-gate delete_stack_cleanup(&dip); 1499*0Sstevel@tonic-gate 1500*0Sstevel@tonic-gate return (rc); 1501*0Sstevel@tonic-gate 1502*0Sstevel@tonic-gate fail: 1503*0Sstevel@tonic-gate backend_tx_rollback(dip.di_tx); 1504*0Sstevel@tonic-gate backend_tx_rollback(dip.di_np_tx); 1505*0Sstevel@tonic-gate delete_stack_cleanup(&dip); 1506*0Sstevel@tonic-gate return (rc); 1507*0Sstevel@tonic-gate } 1508*0Sstevel@tonic-gate 1509*0Sstevel@tonic-gate int 1510*0Sstevel@tonic-gate object_do_create(backend_tx_t *tx, child_info_t *cip, rc_node_t *pp, 1511*0Sstevel@tonic-gate uint32_t type, const char *name, rc_node_t **cpp) 1512*0Sstevel@tonic-gate { 1513*0Sstevel@tonic-gate uint32_t ptype = pp->rn_id.rl_type; 1514*0Sstevel@tonic-gate 1515*0Sstevel@tonic-gate backend_query_t *q; 1516*0Sstevel@tonic-gate uint32_t id; 1517*0Sstevel@tonic-gate rc_node_t *np = NULL; 1518*0Sstevel@tonic-gate int rc; 1519*0Sstevel@tonic-gate object_info_t *ip; 1520*0Sstevel@tonic-gate 1521*0Sstevel@tonic-gate rc_node_lookup_t *lp = &cip->ci_base_nl; 1522*0Sstevel@tonic-gate 1523*0Sstevel@tonic-gate assert(ptype > 0 && ptype < NUM_INFO); 1524*0Sstevel@tonic-gate 1525*0Sstevel@tonic-gate ip = &info[ptype]; 1526*0Sstevel@tonic-gate 1527*0Sstevel@tonic-gate if (type == REP_PROTOCOL_ENTITY_PROPERTYGRP) 1528*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_NOT_APPLICABLE); 1529*0Sstevel@tonic-gate 1530*0Sstevel@tonic-gate if (ip->obj_setup_child_info == NULL || 1531*0Sstevel@tonic-gate ip->obj_query_child == NULL || 1532*0Sstevel@tonic-gate ip->obj_insert_child == NULL) 1533*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_BAD_REQUEST); 1534*0Sstevel@tonic-gate 1535*0Sstevel@tonic-gate if ((rc = (*ip->obj_setup_child_info)(pp, type, cip)) != 1536*0Sstevel@tonic-gate REP_PROTOCOL_SUCCESS) 1537*0Sstevel@tonic-gate return (rc); 1538*0Sstevel@tonic-gate 1539*0Sstevel@tonic-gate q = backend_query_alloc(); 1540*0Sstevel@tonic-gate if ((rc = (*ip->obj_query_child)(q, lp, name)) != 1541*0Sstevel@tonic-gate REP_PROTOCOL_SUCCESS) { 1542*0Sstevel@tonic-gate assert(rc == REP_PROTOCOL_FAIL_BAD_REQUEST); 1543*0Sstevel@tonic-gate backend_query_free(q); 1544*0Sstevel@tonic-gate return (rc); 1545*0Sstevel@tonic-gate } 1546*0Sstevel@tonic-gate 1547*0Sstevel@tonic-gate rc = backend_tx_run_single_int(tx, q, &id); 1548*0Sstevel@tonic-gate backend_query_free(q); 1549*0Sstevel@tonic-gate 1550*0Sstevel@tonic-gate if (rc == REP_PROTOCOL_SUCCESS) 1551*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_EXISTS); 1552*0Sstevel@tonic-gate else if (rc != REP_PROTOCOL_FAIL_NOT_FOUND) 1553*0Sstevel@tonic-gate return (rc); 1554*0Sstevel@tonic-gate 1555*0Sstevel@tonic-gate if ((lp->rl_main_id = backend_new_id(tx, 1556*0Sstevel@tonic-gate info[type].obj_id_space)) == 0) { 1557*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_NO_RESOURCES); 1558*0Sstevel@tonic-gate } 1559*0Sstevel@tonic-gate 1560*0Sstevel@tonic-gate if ((np = rc_node_alloc()) == NULL) 1561*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_NO_RESOURCES); 1562*0Sstevel@tonic-gate 1563*0Sstevel@tonic-gate if ((rc = (*ip->obj_insert_child)(tx, lp, name)) != 1564*0Sstevel@tonic-gate REP_PROTOCOL_SUCCESS) { 1565*0Sstevel@tonic-gate rc_node_destroy(np); 1566*0Sstevel@tonic-gate return (rc); 1567*0Sstevel@tonic-gate } 1568*0Sstevel@tonic-gate 1569*0Sstevel@tonic-gate *cpp = np; 1570*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 1571*0Sstevel@tonic-gate } 1572*0Sstevel@tonic-gate 1573*0Sstevel@tonic-gate /* 1574*0Sstevel@tonic-gate * Fails with 1575*0Sstevel@tonic-gate * _NOT_APPLICABLE - type is _PROPERTYGRP 1576*0Sstevel@tonic-gate * _BAD_REQUEST - cannot create children for this type of node 1577*0Sstevel@tonic-gate * name is invalid 1578*0Sstevel@tonic-gate * _TYPE_MISMATCH - object cannot have children of type type 1579*0Sstevel@tonic-gate * _NO_RESOURCES - out of memory, or could not allocate new id 1580*0Sstevel@tonic-gate * _BACKEND_READONLY 1581*0Sstevel@tonic-gate * _BACKEND_ACCESS 1582*0Sstevel@tonic-gate * _EXISTS - child already exists 1583*0Sstevel@tonic-gate */ 1584*0Sstevel@tonic-gate int 1585*0Sstevel@tonic-gate object_create(rc_node_t *pp, uint32_t type, const char *name, rc_node_t **cpp) 1586*0Sstevel@tonic-gate { 1587*0Sstevel@tonic-gate backend_tx_t *tx; 1588*0Sstevel@tonic-gate rc_node_t *np = NULL; 1589*0Sstevel@tonic-gate child_info_t ci; 1590*0Sstevel@tonic-gate int rc; 1591*0Sstevel@tonic-gate 1592*0Sstevel@tonic-gate if ((rc = backend_tx_begin(pp->rn_id.rl_backend, &tx)) != 1593*0Sstevel@tonic-gate REP_PROTOCOL_SUCCESS) { 1594*0Sstevel@tonic-gate return (rc); 1595*0Sstevel@tonic-gate } 1596*0Sstevel@tonic-gate 1597*0Sstevel@tonic-gate if ((rc = object_do_create(tx, &ci, pp, type, name, &np)) != 1598*0Sstevel@tonic-gate REP_PROTOCOL_SUCCESS) { 1599*0Sstevel@tonic-gate backend_tx_rollback(tx); 1600*0Sstevel@tonic-gate return (rc); 1601*0Sstevel@tonic-gate } 1602*0Sstevel@tonic-gate 1603*0Sstevel@tonic-gate rc = backend_tx_commit(tx); 1604*0Sstevel@tonic-gate if (rc != REP_PROTOCOL_SUCCESS) { 1605*0Sstevel@tonic-gate rc_node_destroy(np); 1606*0Sstevel@tonic-gate return (rc); 1607*0Sstevel@tonic-gate } 1608*0Sstevel@tonic-gate 1609*0Sstevel@tonic-gate *cpp = rc_node_setup(np, &ci.ci_base_nl, name, ci.ci_parent); 1610*0Sstevel@tonic-gate 1611*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 1612*0Sstevel@tonic-gate } 1613*0Sstevel@tonic-gate 1614*0Sstevel@tonic-gate /*ARGSUSED*/ 1615*0Sstevel@tonic-gate int 1616*0Sstevel@tonic-gate object_create_pg(rc_node_t *pp, uint32_t type, const char *name, 1617*0Sstevel@tonic-gate const char *pgtype, uint32_t flags, rc_node_t **cpp) 1618*0Sstevel@tonic-gate { 1619*0Sstevel@tonic-gate uint32_t ptype = pp->rn_id.rl_type; 1620*0Sstevel@tonic-gate backend_tx_t *tx_ro, *tx_wr; 1621*0Sstevel@tonic-gate backend_query_t *q; 1622*0Sstevel@tonic-gate uint32_t id; 1623*0Sstevel@tonic-gate uint32_t gen = 0; 1624*0Sstevel@tonic-gate rc_node_t *np = NULL; 1625*0Sstevel@tonic-gate int rc; 1626*0Sstevel@tonic-gate int rc_wr; 1627*0Sstevel@tonic-gate int rc_ro; 1628*0Sstevel@tonic-gate object_info_t *ip; 1629*0Sstevel@tonic-gate 1630*0Sstevel@tonic-gate int nonpersist = (flags & SCF_PG_FLAG_NONPERSISTENT); 1631*0Sstevel@tonic-gate 1632*0Sstevel@tonic-gate child_info_t ci; 1633*0Sstevel@tonic-gate rc_node_lookup_t *lp = &ci.ci_base_nl; 1634*0Sstevel@tonic-gate 1635*0Sstevel@tonic-gate assert(ptype > 0 && ptype < NUM_INFO); 1636*0Sstevel@tonic-gate 1637*0Sstevel@tonic-gate if (ptype != REP_PROTOCOL_ENTITY_SERVICE && 1638*0Sstevel@tonic-gate ptype != REP_PROTOCOL_ENTITY_INSTANCE) 1639*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_BAD_REQUEST); 1640*0Sstevel@tonic-gate 1641*0Sstevel@tonic-gate ip = &info[ptype]; 1642*0Sstevel@tonic-gate 1643*0Sstevel@tonic-gate assert(ip->obj_setup_child_info != NULL && 1644*0Sstevel@tonic-gate ip->obj_query_child != NULL && 1645*0Sstevel@tonic-gate ip->obj_insert_pg_child != NULL); 1646*0Sstevel@tonic-gate 1647*0Sstevel@tonic-gate if ((rc = (*ip->obj_setup_child_info)(pp, type, &ci)) != 1648*0Sstevel@tonic-gate REP_PROTOCOL_SUCCESS) 1649*0Sstevel@tonic-gate return (rc); 1650*0Sstevel@tonic-gate 1651*0Sstevel@tonic-gate q = backend_query_alloc(); 1652*0Sstevel@tonic-gate if ((rc = (*ip->obj_query_child)(q, lp, name)) != 1653*0Sstevel@tonic-gate REP_PROTOCOL_SUCCESS) { 1654*0Sstevel@tonic-gate backend_query_free(q); 1655*0Sstevel@tonic-gate return (rc); 1656*0Sstevel@tonic-gate } 1657*0Sstevel@tonic-gate 1658*0Sstevel@tonic-gate if (!nonpersist) { 1659*0Sstevel@tonic-gate lp->rl_backend = BACKEND_TYPE_NORMAL; 1660*0Sstevel@tonic-gate rc_wr = backend_tx_begin(BACKEND_TYPE_NORMAL, &tx_wr); 1661*0Sstevel@tonic-gate rc_ro = backend_tx_begin_ro(BACKEND_TYPE_NONPERSIST, &tx_ro); 1662*0Sstevel@tonic-gate } else { 1663*0Sstevel@tonic-gate lp->rl_backend = BACKEND_TYPE_NONPERSIST; 1664*0Sstevel@tonic-gate rc_ro = backend_tx_begin_ro(BACKEND_TYPE_NORMAL, &tx_ro); 1665*0Sstevel@tonic-gate rc_wr = backend_tx_begin(BACKEND_TYPE_NONPERSIST, &tx_wr); 1666*0Sstevel@tonic-gate } 1667*0Sstevel@tonic-gate 1668*0Sstevel@tonic-gate if (rc_wr != REP_PROTOCOL_SUCCESS) { 1669*0Sstevel@tonic-gate rc = rc_wr; 1670*0Sstevel@tonic-gate goto fail; 1671*0Sstevel@tonic-gate } 1672*0Sstevel@tonic-gate if (rc_ro != REP_PROTOCOL_SUCCESS && 1673*0Sstevel@tonic-gate rc_ro != REP_PROTOCOL_FAIL_BACKEND_ACCESS) { 1674*0Sstevel@tonic-gate rc = rc_ro; 1675*0Sstevel@tonic-gate goto fail; 1676*0Sstevel@tonic-gate } 1677*0Sstevel@tonic-gate 1678*0Sstevel@tonic-gate if (tx_ro != NULL) { 1679*0Sstevel@tonic-gate rc = backend_tx_run_single_int(tx_ro, q, &id); 1680*0Sstevel@tonic-gate 1681*0Sstevel@tonic-gate if (rc == REP_PROTOCOL_SUCCESS) { 1682*0Sstevel@tonic-gate backend_query_free(q); 1683*0Sstevel@tonic-gate rc = REP_PROTOCOL_FAIL_EXISTS; 1684*0Sstevel@tonic-gate goto fail; 1685*0Sstevel@tonic-gate } else if (rc != REP_PROTOCOL_FAIL_NOT_FOUND) { 1686*0Sstevel@tonic-gate backend_query_free(q); 1687*0Sstevel@tonic-gate goto fail; 1688*0Sstevel@tonic-gate } 1689*0Sstevel@tonic-gate } 1690*0Sstevel@tonic-gate 1691*0Sstevel@tonic-gate rc = backend_tx_run_single_int(tx_wr, q, &id); 1692*0Sstevel@tonic-gate backend_query_free(q); 1693*0Sstevel@tonic-gate 1694*0Sstevel@tonic-gate if (rc == REP_PROTOCOL_SUCCESS) { 1695*0Sstevel@tonic-gate rc = REP_PROTOCOL_FAIL_EXISTS; 1696*0Sstevel@tonic-gate goto fail; 1697*0Sstevel@tonic-gate } else if (rc != REP_PROTOCOL_FAIL_NOT_FOUND) { 1698*0Sstevel@tonic-gate goto fail; 1699*0Sstevel@tonic-gate } 1700*0Sstevel@tonic-gate 1701*0Sstevel@tonic-gate if (tx_ro != NULL) 1702*0Sstevel@tonic-gate backend_tx_end_ro(tx_ro); 1703*0Sstevel@tonic-gate tx_ro = NULL; 1704*0Sstevel@tonic-gate 1705*0Sstevel@tonic-gate if ((lp->rl_main_id = backend_new_id(tx_wr, 1706*0Sstevel@tonic-gate info[type].obj_id_space)) == 0) { 1707*0Sstevel@tonic-gate rc = REP_PROTOCOL_FAIL_NO_RESOURCES; 1708*0Sstevel@tonic-gate goto fail; 1709*0Sstevel@tonic-gate } 1710*0Sstevel@tonic-gate 1711*0Sstevel@tonic-gate if ((np = rc_node_alloc()) == NULL) { 1712*0Sstevel@tonic-gate rc = REP_PROTOCOL_FAIL_NO_RESOURCES; 1713*0Sstevel@tonic-gate goto fail; 1714*0Sstevel@tonic-gate } 1715*0Sstevel@tonic-gate 1716*0Sstevel@tonic-gate if ((rc = (*ip->obj_insert_pg_child)(tx_wr, lp, name, pgtype, flags, 1717*0Sstevel@tonic-gate gen)) != REP_PROTOCOL_SUCCESS) { 1718*0Sstevel@tonic-gate rc_node_destroy(np); 1719*0Sstevel@tonic-gate goto fail; 1720*0Sstevel@tonic-gate } 1721*0Sstevel@tonic-gate 1722*0Sstevel@tonic-gate rc = backend_tx_commit(tx_wr); 1723*0Sstevel@tonic-gate if (rc != REP_PROTOCOL_SUCCESS) { 1724*0Sstevel@tonic-gate rc_node_destroy(np); 1725*0Sstevel@tonic-gate return (rc); 1726*0Sstevel@tonic-gate } 1727*0Sstevel@tonic-gate 1728*0Sstevel@tonic-gate *cpp = rc_node_setup_pg(np, lp, name, pgtype, flags, gen, ci.ci_parent); 1729*0Sstevel@tonic-gate 1730*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 1731*0Sstevel@tonic-gate 1732*0Sstevel@tonic-gate fail: 1733*0Sstevel@tonic-gate if (tx_ro != NULL) 1734*0Sstevel@tonic-gate backend_tx_end_ro(tx_ro); 1735*0Sstevel@tonic-gate if (tx_wr != NULL) 1736*0Sstevel@tonic-gate backend_tx_rollback(tx_wr); 1737*0Sstevel@tonic-gate return (rc); 1738*0Sstevel@tonic-gate } 1739*0Sstevel@tonic-gate 1740*0Sstevel@tonic-gate /* 1741*0Sstevel@tonic-gate * Given a row of snaplevel number, snaplevel id, service id, service name, 1742*0Sstevel@tonic-gate * instance id, & instance name, create a rc_snaplevel_t & prepend it onto the 1743*0Sstevel@tonic-gate * rs_levels list of the rc_snapshot_t passed in as data. 1744*0Sstevel@tonic-gate * Returns _CONTINUE on success or _ABORT if any allocations fail. 1745*0Sstevel@tonic-gate */ 1746*0Sstevel@tonic-gate /*ARGSUSED*/ 1747*0Sstevel@tonic-gate static int 1748*0Sstevel@tonic-gate fill_snapshot_cb(void *data, int columns, char **vals, char **names) 1749*0Sstevel@tonic-gate { 1750*0Sstevel@tonic-gate rc_snapshot_t *sp = data; 1751*0Sstevel@tonic-gate rc_snaplevel_t *lvl; 1752*0Sstevel@tonic-gate char *num = vals[0]; 1753*0Sstevel@tonic-gate char *id = vals[1]; 1754*0Sstevel@tonic-gate char *service_id = vals[2]; 1755*0Sstevel@tonic-gate char *service = vals[3]; 1756*0Sstevel@tonic-gate char *instance_id = vals[4]; 1757*0Sstevel@tonic-gate char *instance = vals[5]; 1758*0Sstevel@tonic-gate assert(columns == 6); 1759*0Sstevel@tonic-gate 1760*0Sstevel@tonic-gate lvl = uu_zalloc(sizeof (*lvl)); 1761*0Sstevel@tonic-gate if (lvl == NULL) 1762*0Sstevel@tonic-gate return (BACKEND_CALLBACK_ABORT); 1763*0Sstevel@tonic-gate lvl->rsl_parent = sp; 1764*0Sstevel@tonic-gate lvl->rsl_next = sp->rs_levels; 1765*0Sstevel@tonic-gate sp->rs_levels = lvl; 1766*0Sstevel@tonic-gate 1767*0Sstevel@tonic-gate if (uu_strtouint(num, &lvl->rsl_level_num, 1768*0Sstevel@tonic-gate sizeof (lvl->rsl_level_num), 0, 0, 0) == -1 || 1769*0Sstevel@tonic-gate uu_strtouint(id, &lvl->rsl_level_id, 1770*0Sstevel@tonic-gate sizeof (lvl->rsl_level_id), 0, 0, 0) == -1 || 1771*0Sstevel@tonic-gate uu_strtouint(service_id, &lvl->rsl_service_id, 1772*0Sstevel@tonic-gate sizeof (lvl->rsl_level_num), 0, 0, 0) == -1 || 1773*0Sstevel@tonic-gate (instance_id != NULL && 1774*0Sstevel@tonic-gate uu_strtouint(instance_id, &lvl->rsl_instance_id, 1775*0Sstevel@tonic-gate sizeof (lvl->rsl_instance_id), 0, 0, 0) == -1)) { 1776*0Sstevel@tonic-gate backend_panic("invalid integer in database"); 1777*0Sstevel@tonic-gate } 1778*0Sstevel@tonic-gate 1779*0Sstevel@tonic-gate lvl->rsl_scope = (const char *)"localhost"; 1780*0Sstevel@tonic-gate lvl->rsl_service = strdup(service); 1781*0Sstevel@tonic-gate if (lvl->rsl_service == NULL) { 1782*0Sstevel@tonic-gate uu_free(lvl); 1783*0Sstevel@tonic-gate return (BACKEND_CALLBACK_ABORT); 1784*0Sstevel@tonic-gate } 1785*0Sstevel@tonic-gate if (instance) { 1786*0Sstevel@tonic-gate assert(lvl->rsl_instance_id != 0); 1787*0Sstevel@tonic-gate lvl->rsl_instance = strdup(instance); 1788*0Sstevel@tonic-gate if (lvl->rsl_instance == NULL) { 1789*0Sstevel@tonic-gate free((void *)lvl->rsl_instance); 1790*0Sstevel@tonic-gate uu_free(lvl); 1791*0Sstevel@tonic-gate return (BACKEND_CALLBACK_ABORT); 1792*0Sstevel@tonic-gate } 1793*0Sstevel@tonic-gate } else { 1794*0Sstevel@tonic-gate assert(lvl->rsl_instance_id == 0); 1795*0Sstevel@tonic-gate } 1796*0Sstevel@tonic-gate 1797*0Sstevel@tonic-gate return (BACKEND_CALLBACK_CONTINUE); 1798*0Sstevel@tonic-gate } 1799*0Sstevel@tonic-gate 1800*0Sstevel@tonic-gate /* 1801*0Sstevel@tonic-gate * Populate sp's rs_levels list from the snaplevel_tbl table. 1802*0Sstevel@tonic-gate * Fails with 1803*0Sstevel@tonic-gate * _NO_RESOURCES 1804*0Sstevel@tonic-gate */ 1805*0Sstevel@tonic-gate int 1806*0Sstevel@tonic-gate object_fill_snapshot(rc_snapshot_t *sp) 1807*0Sstevel@tonic-gate { 1808*0Sstevel@tonic-gate backend_query_t *q; 1809*0Sstevel@tonic-gate rc_snaplevel_t *sl; 1810*0Sstevel@tonic-gate int result; 1811*0Sstevel@tonic-gate int i; 1812*0Sstevel@tonic-gate 1813*0Sstevel@tonic-gate q = backend_query_alloc(); 1814*0Sstevel@tonic-gate backend_query_add(q, 1815*0Sstevel@tonic-gate "SELECT snap_level_num, snap_level_id, " 1816*0Sstevel@tonic-gate " snap_level_service_id, snap_level_service, " 1817*0Sstevel@tonic-gate " snap_level_instance_id, snap_level_instance " 1818*0Sstevel@tonic-gate "FROM snaplevel_tbl " 1819*0Sstevel@tonic-gate "WHERE snap_id = %d " 1820*0Sstevel@tonic-gate "ORDER BY snap_level_id DESC", 1821*0Sstevel@tonic-gate sp->rs_snap_id); 1822*0Sstevel@tonic-gate 1823*0Sstevel@tonic-gate result = backend_run(BACKEND_TYPE_NORMAL, q, fill_snapshot_cb, sp); 1824*0Sstevel@tonic-gate if (result == REP_PROTOCOL_DONE) 1825*0Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_NO_RESOURCES; 1826*0Sstevel@tonic-gate backend_query_free(q); 1827*0Sstevel@tonic-gate 1828*0Sstevel@tonic-gate if (result == REP_PROTOCOL_SUCCESS) { 1829*0Sstevel@tonic-gate i = 0; 1830*0Sstevel@tonic-gate for (sl = sp->rs_levels; sl != NULL; sl = sl->rsl_next) { 1831*0Sstevel@tonic-gate if (sl->rsl_level_num != ++i) { 1832*0Sstevel@tonic-gate backend_panic("snaplevels corrupt; expected " 1833*0Sstevel@tonic-gate "level %d, got %d", i, sl->rsl_level_num); 1834*0Sstevel@tonic-gate } 1835*0Sstevel@tonic-gate } 1836*0Sstevel@tonic-gate } 1837*0Sstevel@tonic-gate return (result); 1838*0Sstevel@tonic-gate } 1839*0Sstevel@tonic-gate 1840*0Sstevel@tonic-gate /*ARGSUSED*/ 1841*0Sstevel@tonic-gate static int 1842*0Sstevel@tonic-gate object_copy_string(void *data_arg, int columns, char **vals, char **names) 1843*0Sstevel@tonic-gate { 1844*0Sstevel@tonic-gate char **data = data_arg; 1845*0Sstevel@tonic-gate 1846*0Sstevel@tonic-gate assert(columns == 1); 1847*0Sstevel@tonic-gate 1848*0Sstevel@tonic-gate if (*data != NULL) 1849*0Sstevel@tonic-gate free(*data); 1850*0Sstevel@tonic-gate *data = NULL; 1851*0Sstevel@tonic-gate 1852*0Sstevel@tonic-gate if (vals[0] != NULL) { 1853*0Sstevel@tonic-gate if ((*data = strdup(vals[0])) == NULL) 1854*0Sstevel@tonic-gate return (BACKEND_CALLBACK_ABORT); 1855*0Sstevel@tonic-gate } 1856*0Sstevel@tonic-gate 1857*0Sstevel@tonic-gate return (BACKEND_CALLBACK_CONTINUE); 1858*0Sstevel@tonic-gate } 1859*0Sstevel@tonic-gate 1860*0Sstevel@tonic-gate struct snaplevel_add_info { 1861*0Sstevel@tonic-gate backend_query_t *sai_q; 1862*0Sstevel@tonic-gate uint32_t sai_level_id; 1863*0Sstevel@tonic-gate int sai_used; /* sai_q has been used */ 1864*0Sstevel@tonic-gate }; 1865*0Sstevel@tonic-gate 1866*0Sstevel@tonic-gate /*ARGSUSED*/ 1867*0Sstevel@tonic-gate static int 1868*0Sstevel@tonic-gate object_snaplevel_process_pg(void *data_arg, int columns, char **vals, 1869*0Sstevel@tonic-gate char **names) 1870*0Sstevel@tonic-gate { 1871*0Sstevel@tonic-gate struct snaplevel_add_info *data = data_arg; 1872*0Sstevel@tonic-gate 1873*0Sstevel@tonic-gate assert(columns == 5); 1874*0Sstevel@tonic-gate 1875*0Sstevel@tonic-gate backend_query_add(data->sai_q, 1876*0Sstevel@tonic-gate "INSERT INTO snaplevel_lnk_tbl " 1877*0Sstevel@tonic-gate " (snaplvl_level_id, snaplvl_pg_id, snaplvl_pg_name, " 1878*0Sstevel@tonic-gate " snaplvl_pg_type, snaplvl_pg_flags, snaplvl_gen_id)" 1879*0Sstevel@tonic-gate "VALUES (%d, %s, '%q', '%q', %s, %s);", 1880*0Sstevel@tonic-gate data->sai_level_id, vals[0], vals[1], vals[2], vals[3], vals[4]); 1881*0Sstevel@tonic-gate 1882*0Sstevel@tonic-gate data->sai_used = 1; 1883*0Sstevel@tonic-gate 1884*0Sstevel@tonic-gate return (BACKEND_CALLBACK_CONTINUE); 1885*0Sstevel@tonic-gate } 1886*0Sstevel@tonic-gate 1887*0Sstevel@tonic-gate /*ARGSUSED*/ 1888*0Sstevel@tonic-gate static int 1889*0Sstevel@tonic-gate object_snapshot_add_level(backend_tx_t *tx, uint32_t snap_id, 1890*0Sstevel@tonic-gate uint32_t snap_level_num, uint32_t svc_id, const char *svc_name, 1891*0Sstevel@tonic-gate uint32_t inst_id, const char *inst_name) 1892*0Sstevel@tonic-gate { 1893*0Sstevel@tonic-gate struct snaplevel_add_info data; 1894*0Sstevel@tonic-gate backend_query_t *q; 1895*0Sstevel@tonic-gate int result; 1896*0Sstevel@tonic-gate 1897*0Sstevel@tonic-gate assert((snap_level_num == 1 && inst_name != NULL) || 1898*0Sstevel@tonic-gate snap_level_num == 2 && inst_name == NULL); 1899*0Sstevel@tonic-gate 1900*0Sstevel@tonic-gate data.sai_level_id = backend_new_id(tx, BACKEND_ID_SNAPLEVEL); 1901*0Sstevel@tonic-gate if (data.sai_level_id == 0) { 1902*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_NO_RESOURCES); 1903*0Sstevel@tonic-gate } 1904*0Sstevel@tonic-gate 1905*0Sstevel@tonic-gate result = backend_tx_run_update(tx, 1906*0Sstevel@tonic-gate "INSERT INTO snaplevel_tbl " 1907*0Sstevel@tonic-gate " (snap_id, snap_level_num, snap_level_id, " 1908*0Sstevel@tonic-gate " snap_level_service_id, snap_level_service, " 1909*0Sstevel@tonic-gate " snap_level_instance_id, snap_level_instance) " 1910*0Sstevel@tonic-gate "VALUES (%d, %d, %d, %d, %Q, %d, %Q);", 1911*0Sstevel@tonic-gate snap_id, snap_level_num, data.sai_level_id, svc_id, svc_name, 1912*0Sstevel@tonic-gate inst_id, inst_name); 1913*0Sstevel@tonic-gate 1914*0Sstevel@tonic-gate q = backend_query_alloc(); 1915*0Sstevel@tonic-gate backend_query_add(q, 1916*0Sstevel@tonic-gate "SELECT pg_id, pg_name, pg_type, pg_flags, pg_gen_id FROM pg_tbl " 1917*0Sstevel@tonic-gate "WHERE (pg_parent_id = %d);", 1918*0Sstevel@tonic-gate (inst_name != NULL)? inst_id : svc_id); 1919*0Sstevel@tonic-gate 1920*0Sstevel@tonic-gate data.sai_q = backend_query_alloc(); 1921*0Sstevel@tonic-gate data.sai_used = 0; 1922*0Sstevel@tonic-gate result = backend_tx_run(tx, q, object_snaplevel_process_pg, 1923*0Sstevel@tonic-gate &data); 1924*0Sstevel@tonic-gate backend_query_free(q); 1925*0Sstevel@tonic-gate 1926*0Sstevel@tonic-gate if (result == REP_PROTOCOL_SUCCESS && data.sai_used != 0) 1927*0Sstevel@tonic-gate result = backend_tx_run(tx, data.sai_q, NULL, NULL); 1928*0Sstevel@tonic-gate backend_query_free(data.sai_q); 1929*0Sstevel@tonic-gate 1930*0Sstevel@tonic-gate return (result); 1931*0Sstevel@tonic-gate } 1932*0Sstevel@tonic-gate 1933*0Sstevel@tonic-gate /* 1934*0Sstevel@tonic-gate * Fails with: 1935*0Sstevel@tonic-gate * _NO_RESOURCES - no new id or out of disk space 1936*0Sstevel@tonic-gate * _BACKEND_READONLY - persistent backend is read-only 1937*0Sstevel@tonic-gate */ 1938*0Sstevel@tonic-gate static int 1939*0Sstevel@tonic-gate object_snapshot_do_take(uint32_t instid, const char *inst_name, 1940*0Sstevel@tonic-gate uint32_t svcid, const char *svc_name, 1941*0Sstevel@tonic-gate backend_tx_t **tx_out, uint32_t *snapid_out) 1942*0Sstevel@tonic-gate { 1943*0Sstevel@tonic-gate backend_tx_t *tx; 1944*0Sstevel@tonic-gate backend_query_t *q; 1945*0Sstevel@tonic-gate int result; 1946*0Sstevel@tonic-gate 1947*0Sstevel@tonic-gate char *svc_name_alloc = NULL; 1948*0Sstevel@tonic-gate char *inst_name_alloc = NULL; 1949*0Sstevel@tonic-gate uint32_t snapid; 1950*0Sstevel@tonic-gate 1951*0Sstevel@tonic-gate result = backend_tx_begin(BACKEND_TYPE_NORMAL, &tx); 1952*0Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 1953*0Sstevel@tonic-gate return (result); 1954*0Sstevel@tonic-gate 1955*0Sstevel@tonic-gate snapid = backend_new_id(tx, BACKEND_ID_SNAPSHOT); 1956*0Sstevel@tonic-gate if (snapid == 0) { 1957*0Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_NO_RESOURCES; 1958*0Sstevel@tonic-gate goto fail; 1959*0Sstevel@tonic-gate } 1960*0Sstevel@tonic-gate 1961*0Sstevel@tonic-gate if (svc_name == NULL) { 1962*0Sstevel@tonic-gate q = backend_query_alloc(); 1963*0Sstevel@tonic-gate backend_query_add(q, 1964*0Sstevel@tonic-gate "SELECT svc_name FROM service_tbl " 1965*0Sstevel@tonic-gate "WHERE (svc_id = %d)", svcid); 1966*0Sstevel@tonic-gate result = backend_tx_run(tx, q, object_copy_string, 1967*0Sstevel@tonic-gate &svc_name_alloc); 1968*0Sstevel@tonic-gate backend_query_free(q); 1969*0Sstevel@tonic-gate 1970*0Sstevel@tonic-gate svc_name = svc_name_alloc; 1971*0Sstevel@tonic-gate 1972*0Sstevel@tonic-gate if (result == REP_PROTOCOL_DONE) { 1973*0Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_NO_RESOURCES; 1974*0Sstevel@tonic-gate goto fail; 1975*0Sstevel@tonic-gate } 1976*0Sstevel@tonic-gate if (result == REP_PROTOCOL_SUCCESS && svc_name == NULL) 1977*0Sstevel@tonic-gate backend_panic("unable to find name for svc id %d\n", 1978*0Sstevel@tonic-gate svcid); 1979*0Sstevel@tonic-gate 1980*0Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 1981*0Sstevel@tonic-gate goto fail; 1982*0Sstevel@tonic-gate } 1983*0Sstevel@tonic-gate 1984*0Sstevel@tonic-gate if (inst_name == NULL) { 1985*0Sstevel@tonic-gate q = backend_query_alloc(); 1986*0Sstevel@tonic-gate backend_query_add(q, 1987*0Sstevel@tonic-gate "SELECT instance_name FROM instance_tbl " 1988*0Sstevel@tonic-gate "WHERE (instance_id = %d)", instid); 1989*0Sstevel@tonic-gate result = backend_tx_run(tx, q, object_copy_string, 1990*0Sstevel@tonic-gate &inst_name_alloc); 1991*0Sstevel@tonic-gate backend_query_free(q); 1992*0Sstevel@tonic-gate 1993*0Sstevel@tonic-gate inst_name = inst_name_alloc; 1994*0Sstevel@tonic-gate 1995*0Sstevel@tonic-gate if (result == REP_PROTOCOL_DONE) { 1996*0Sstevel@tonic-gate result = REP_PROTOCOL_FAIL_NO_RESOURCES; 1997*0Sstevel@tonic-gate goto fail; 1998*0Sstevel@tonic-gate } 1999*0Sstevel@tonic-gate 2000*0Sstevel@tonic-gate if (result == REP_PROTOCOL_SUCCESS && inst_name == NULL) 2001*0Sstevel@tonic-gate backend_panic( 2002*0Sstevel@tonic-gate "unable to find name for instance id %d\n", instid); 2003*0Sstevel@tonic-gate 2004*0Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 2005*0Sstevel@tonic-gate goto fail; 2006*0Sstevel@tonic-gate } 2007*0Sstevel@tonic-gate 2008*0Sstevel@tonic-gate result = object_snapshot_add_level(tx, snapid, 1, 2009*0Sstevel@tonic-gate svcid, svc_name, instid, inst_name); 2010*0Sstevel@tonic-gate 2011*0Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 2012*0Sstevel@tonic-gate goto fail; 2013*0Sstevel@tonic-gate 2014*0Sstevel@tonic-gate result = object_snapshot_add_level(tx, snapid, 2, 2015*0Sstevel@tonic-gate svcid, svc_name, 0, NULL); 2016*0Sstevel@tonic-gate 2017*0Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 2018*0Sstevel@tonic-gate goto fail; 2019*0Sstevel@tonic-gate 2020*0Sstevel@tonic-gate *snapid_out = snapid; 2021*0Sstevel@tonic-gate *tx_out = tx; 2022*0Sstevel@tonic-gate 2023*0Sstevel@tonic-gate free(svc_name_alloc); 2024*0Sstevel@tonic-gate free(inst_name_alloc); 2025*0Sstevel@tonic-gate 2026*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 2027*0Sstevel@tonic-gate 2028*0Sstevel@tonic-gate fail: 2029*0Sstevel@tonic-gate backend_tx_rollback(tx); 2030*0Sstevel@tonic-gate free(svc_name_alloc); 2031*0Sstevel@tonic-gate free(inst_name_alloc); 2032*0Sstevel@tonic-gate return (result); 2033*0Sstevel@tonic-gate } 2034*0Sstevel@tonic-gate 2035*0Sstevel@tonic-gate /* 2036*0Sstevel@tonic-gate * Fails with: 2037*0Sstevel@tonic-gate * _TYPE_MISMATCH - pp is not an instance 2038*0Sstevel@tonic-gate * _NO_RESOURCES - no new id or out of disk space 2039*0Sstevel@tonic-gate * _BACKEND_READONLY - persistent backend is read-only 2040*0Sstevel@tonic-gate */ 2041*0Sstevel@tonic-gate int 2042*0Sstevel@tonic-gate object_snapshot_take_new(rc_node_t *pp, 2043*0Sstevel@tonic-gate const char *svc_name, const char *inst_name, 2044*0Sstevel@tonic-gate const char *name, rc_node_t **outp) 2045*0Sstevel@tonic-gate { 2046*0Sstevel@tonic-gate rc_node_lookup_t *insti = &pp->rn_id; 2047*0Sstevel@tonic-gate 2048*0Sstevel@tonic-gate uint32_t instid = insti->rl_main_id; 2049*0Sstevel@tonic-gate uint32_t svcid = insti->rl_ids[ID_SERVICE]; 2050*0Sstevel@tonic-gate uint32_t snapid = 0; 2051*0Sstevel@tonic-gate backend_tx_t *tx = NULL; 2052*0Sstevel@tonic-gate child_info_t ci; 2053*0Sstevel@tonic-gate rc_node_t *np; 2054*0Sstevel@tonic-gate int result; 2055*0Sstevel@tonic-gate 2056*0Sstevel@tonic-gate if (insti->rl_type != REP_PROTOCOL_ENTITY_INSTANCE) 2057*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_TYPE_MISMATCH); 2058*0Sstevel@tonic-gate 2059*0Sstevel@tonic-gate result = object_snapshot_do_take(instid, inst_name, svcid, svc_name, 2060*0Sstevel@tonic-gate &tx, &snapid); 2061*0Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 2062*0Sstevel@tonic-gate return (result); 2063*0Sstevel@tonic-gate 2064*0Sstevel@tonic-gate if ((result = object_do_create(tx, &ci, pp, 2065*0Sstevel@tonic-gate REP_PROTOCOL_ENTITY_SNAPSHOT, name, &np)) != REP_PROTOCOL_SUCCESS) { 2066*0Sstevel@tonic-gate backend_tx_rollback(tx); 2067*0Sstevel@tonic-gate return (result); 2068*0Sstevel@tonic-gate } 2069*0Sstevel@tonic-gate 2070*0Sstevel@tonic-gate /* 2071*0Sstevel@tonic-gate * link the new object to the new snapshot. 2072*0Sstevel@tonic-gate */ 2073*0Sstevel@tonic-gate np->rn_snapshot_id = snapid; 2074*0Sstevel@tonic-gate 2075*0Sstevel@tonic-gate result = backend_tx_run_update(tx, 2076*0Sstevel@tonic-gate "UPDATE snapshot_lnk_tbl SET lnk_snap_id = %d WHERE lnk_id = %d;", 2077*0Sstevel@tonic-gate snapid, ci.ci_base_nl.rl_main_id); 2078*0Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) { 2079*0Sstevel@tonic-gate backend_tx_rollback(tx); 2080*0Sstevel@tonic-gate rc_node_destroy(np); 2081*0Sstevel@tonic-gate return (result); 2082*0Sstevel@tonic-gate } 2083*0Sstevel@tonic-gate result = backend_tx_commit(tx); 2084*0Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) { 2085*0Sstevel@tonic-gate rc_node_destroy(np); 2086*0Sstevel@tonic-gate return (result); 2087*0Sstevel@tonic-gate } 2088*0Sstevel@tonic-gate 2089*0Sstevel@tonic-gate *outp = rc_node_setup(np, &ci.ci_base_nl, name, ci.ci_parent); 2090*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 2091*0Sstevel@tonic-gate } 2092*0Sstevel@tonic-gate 2093*0Sstevel@tonic-gate /* 2094*0Sstevel@tonic-gate * Fails with: 2095*0Sstevel@tonic-gate * _TYPE_MISMATCH - pp is not an instance 2096*0Sstevel@tonic-gate * _NO_RESOURCES - no new id or out of disk space 2097*0Sstevel@tonic-gate * _BACKEND_READONLY - persistent backend is read-only 2098*0Sstevel@tonic-gate */ 2099*0Sstevel@tonic-gate int 2100*0Sstevel@tonic-gate object_snapshot_attach(rc_node_lookup_t *snapi, uint32_t *snapid_ptr, 2101*0Sstevel@tonic-gate int takesnap) 2102*0Sstevel@tonic-gate { 2103*0Sstevel@tonic-gate uint32_t svcid = snapi->rl_ids[ID_SERVICE]; 2104*0Sstevel@tonic-gate uint32_t instid = snapi->rl_ids[ID_INSTANCE]; 2105*0Sstevel@tonic-gate uint32_t snapid = *snapid_ptr; 2106*0Sstevel@tonic-gate uint32_t oldsnapid = 0; 2107*0Sstevel@tonic-gate backend_tx_t *tx = NULL; 2108*0Sstevel@tonic-gate backend_query_t *q; 2109*0Sstevel@tonic-gate int result; 2110*0Sstevel@tonic-gate 2111*0Sstevel@tonic-gate delete_info_t dip; 2112*0Sstevel@tonic-gate delete_ent_t de; 2113*0Sstevel@tonic-gate 2114*0Sstevel@tonic-gate if (snapi->rl_type != REP_PROTOCOL_ENTITY_SNAPSHOT) 2115*0Sstevel@tonic-gate return (REP_PROTOCOL_FAIL_TYPE_MISMATCH); 2116*0Sstevel@tonic-gate 2117*0Sstevel@tonic-gate if (takesnap) { 2118*0Sstevel@tonic-gate result = object_snapshot_do_take(instid, NULL, 2119*0Sstevel@tonic-gate svcid, NULL, &tx, &snapid); 2120*0Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 2121*0Sstevel@tonic-gate return (result); 2122*0Sstevel@tonic-gate } else { 2123*0Sstevel@tonic-gate result = backend_tx_begin(BACKEND_TYPE_NORMAL, &tx); 2124*0Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 2125*0Sstevel@tonic-gate return (result); 2126*0Sstevel@tonic-gate } 2127*0Sstevel@tonic-gate 2128*0Sstevel@tonic-gate q = backend_query_alloc(); 2129*0Sstevel@tonic-gate backend_query_add(q, 2130*0Sstevel@tonic-gate "SELECT lnk_snap_id FROM snapshot_lnk_tbl WHERE lnk_id = %d; " 2131*0Sstevel@tonic-gate "UPDATE snapshot_lnk_tbl SET lnk_snap_id = %d WHERE lnk_id = %d;", 2132*0Sstevel@tonic-gate snapi->rl_main_id, snapid, snapi->rl_main_id); 2133*0Sstevel@tonic-gate result = backend_tx_run_single_int(tx, q, &oldsnapid); 2134*0Sstevel@tonic-gate backend_query_free(q); 2135*0Sstevel@tonic-gate 2136*0Sstevel@tonic-gate if (result == REP_PROTOCOL_FAIL_NOT_FOUND) { 2137*0Sstevel@tonic-gate backend_tx_rollback(tx); 2138*0Sstevel@tonic-gate backend_panic("unable to find snapshot id %d", 2139*0Sstevel@tonic-gate snapi->rl_main_id); 2140*0Sstevel@tonic-gate } 2141*0Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 2142*0Sstevel@tonic-gate goto fail; 2143*0Sstevel@tonic-gate 2144*0Sstevel@tonic-gate /* 2145*0Sstevel@tonic-gate * Now we use the delete stack to handle the possible unreferencing 2146*0Sstevel@tonic-gate * of oldsnapid. 2147*0Sstevel@tonic-gate */ 2148*0Sstevel@tonic-gate (void) memset(&dip, 0, sizeof (dip)); 2149*0Sstevel@tonic-gate dip.di_tx = tx; 2150*0Sstevel@tonic-gate dip.di_np_tx = NULL; /* no need for non-persistant backend */ 2151*0Sstevel@tonic-gate 2152*0Sstevel@tonic-gate if ((result = delete_stack_push(&dip, BACKEND_TYPE_NORMAL, 2153*0Sstevel@tonic-gate &snaplevel_tbl_delete, oldsnapid, 0)) != REP_PROTOCOL_SUCCESS) 2154*0Sstevel@tonic-gate goto fail; 2155*0Sstevel@tonic-gate 2156*0Sstevel@tonic-gate while (delete_stack_pop(&dip, &de)) { 2157*0Sstevel@tonic-gate result = (*de.de_cb)(&dip, &de); 2158*0Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 2159*0Sstevel@tonic-gate goto fail; 2160*0Sstevel@tonic-gate } 2161*0Sstevel@tonic-gate 2162*0Sstevel@tonic-gate result = backend_tx_commit(tx); 2163*0Sstevel@tonic-gate if (result != REP_PROTOCOL_SUCCESS) 2164*0Sstevel@tonic-gate goto fail; 2165*0Sstevel@tonic-gate 2166*0Sstevel@tonic-gate delete_stack_cleanup(&dip); 2167*0Sstevel@tonic-gate *snapid_ptr = snapid; 2168*0Sstevel@tonic-gate return (REP_PROTOCOL_SUCCESS); 2169*0Sstevel@tonic-gate 2170*0Sstevel@tonic-gate fail: 2171*0Sstevel@tonic-gate backend_tx_rollback(tx); 2172*0Sstevel@tonic-gate delete_stack_cleanup(&dip); 2173*0Sstevel@tonic-gate return (result); 2174*0Sstevel@tonic-gate } 2175