/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* file_object.c - enter objects into and load them from the backend
*
* The primary entry points in this layer are object_create(),
* object_create_pg(), object_delete(), and object_fill_children(). They each
* take an rc_node_t and use the functions in the object_info_t info array for
* the node's type.
*/
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "configd.h"
#include "repcache_protocol.h"
typedef struct child_info {
} child_info_t;
struct delete_ent {
};
struct delete_stack {
};
struct delete_info {
};
typedef struct object_info {
const char *);
const char *);
static void
{
backend_panic("invalid integer \"%s\" in field \"%s\"",
}
static int
{
return (REP_PROTOCOL_FAIL_NO_RESOURCES);
}
}
return (REP_PROTOCOL_SUCCESS);
}
static int
{
return (0);
}
return (0);
return (1);
}
static void
{
}
}
}
struct delete_cb_info {
int dci_result;
};
/*ARGSUSED*/
static int
{
return (BACKEND_CALLBACK_ABORT);
return (BACKEND_CALLBACK_CONTINUE);
}
static int
{
int r;
backend_query_t *q;
q = backend_query_alloc();
"SELECT 1 FROM prop_lnk_tbl WHERE (lnk_val_id = %d); "
"DELETE FROM value_tbl WHERE (value_id = %d); ",
if (r == REP_PROTOCOL_DONE)
return (REP_PROTOCOL_SUCCESS); /* still in use */
return (r);
}
static int
{
int r;
backend_query_t *q;
/*
* For non-persistent backends, we could only have one parent, and
* he's already been deleted.
*
* For normal backends, we need to check to see if we're in
* a snapshot or are the active generation for the property
* group. If we are, there's nothing to be done.
*/
if (be == BACKEND_TYPE_NORMAL) {
q = backend_query_alloc();
"SELECT 1 "
"FROM pg_tbl "
"WHERE (pg_id = %d AND pg_gen_id = %d); "
"SELECT 1 "
"FROM snaplevel_lnk_tbl "
"WHERE (snaplvl_pg_id = %d AND snaplvl_gen_id = %d);",
if (r == REP_PROTOCOL_DONE)
return (REP_PROTOCOL_SUCCESS); /* still in use */
}
q = backend_query_alloc();
"SELECT DISTINCT lnk_val_id, 0 FROM prop_lnk_tbl "
"WHERE "
" (lnk_pg_id = %d AND lnk_gen_id = %d AND lnk_val_id NOTNULL); "
"DELETE FROM prop_lnk_tbl "
"WHERE (lnk_pg_id = %d AND lnk_gen_id = %d)",
if (r == REP_PROTOCOL_DONE) {
return (info.dci_result);
}
return (r);
}
static int
{
backend_query_t *q;
int r;
q = backend_query_alloc();
"SELECT pg_gen_id FROM pg_tbl WHERE pg_id = %d; "
"DELETE FROM pg_tbl WHERE pg_id = %d",
if (r != REP_PROTOCOL_SUCCESS)
return (r);
}
static int
{
backend_query_t *q;
int r;
q = backend_query_alloc();
"SELECT snaplvl_pg_id, snaplvl_gen_id "
" FROM snaplevel_lnk_tbl "
" WHERE snaplvl_level_id = %d; "
"DELETE FROM snaplevel_lnk_tbl WHERE snaplvl_level_id = %d",
if (r == REP_PROTOCOL_DONE) {
return (info.dci_result);
}
return (r);
}
static int
{
backend_query_t *q;
int r;
q = backend_query_alloc();
"SELECT 1 FROM snapshot_lnk_tbl WHERE lnk_snap_id = %d",
if (r == REP_PROTOCOL_DONE)
return (REP_PROTOCOL_SUCCESS); /* still in use */
q = backend_query_alloc();
"SELECT snap_level_id, 0 FROM snaplevel_tbl WHERE snap_id = %d;"
"DELETE FROM snaplevel_tbl WHERE snap_id = %d",
if (r == REP_PROTOCOL_DONE) {
return (info.dci_result);
}
return (r);
}
static int
{
backend_query_t *q;
int r;
q = backend_query_alloc();
"SELECT lnk_snap_id FROM snapshot_lnk_tbl WHERE lnk_id = %d; "
"DELETE FROM snapshot_lnk_tbl WHERE lnk_id = %d",
if (r != REP_PROTOCOL_SUCCESS)
return (r);
}
static int
{
backend_query_t *q;
int r;
q = backend_query_alloc();
"SELECT pg_id, 0 FROM pg_tbl WHERE pg_parent_id = %d",
if (r == REP_PROTOCOL_DONE) {
return (info.dci_result);
}
if (r != REP_PROTOCOL_SUCCESS) {
return (r);
}
&info);
if (r == REP_PROTOCOL_DONE) {
return (info.dci_result);
}
if (r != REP_PROTOCOL_SUCCESS) {
return (r);
}
}
return (REP_PROTOCOL_SUCCESS);
}
static int
{
int r;
if (r != REP_PROTOCOL_SUCCESS)
return (r);
}
static int
{
int r;
backend_query_t *q;
if (r != REP_PROTOCOL_SUCCESS)
return (r);
if (r != REP_PROTOCOL_SUCCESS)
return (r);
q = backend_query_alloc();
"SELECT lnk_id, 0 FROM snapshot_lnk_tbl WHERE lnk_inst_id = %d",
if (r == REP_PROTOCOL_DONE) {
return (info.dci_result);
}
return (r);
}
/*ARGSUSED*/
static int
{
const char *name;
const char *cur;
columns--;
columns--;
return (BACKEND_CALLBACK_ABORT);
return (BACKEND_CALLBACK_CONTINUE);
}
/*ARGSUSED*/
static int
{
const char *name;
const char *cur;
const char *snap;
columns--;
columns--;
columns--;
return (BACKEND_CALLBACK_ABORT);
return (BACKEND_CALLBACK_CONTINUE);
}
/*ARGSUSED*/
static int
{
const char *name;
const char *type;
const char *cur;
columns--;
columns--;
columns--;
columns--;
columns--;
return (BACKEND_CALLBACK_ABORT);
return (BACKEND_CALLBACK_ABORT);
}
return (BACKEND_CALLBACK_CONTINUE);
}
struct property_value_info {
char *pvi_base;
};
/*ARGSUSED*/
static int
{
return (BACKEND_CALLBACK_CONTINUE);
}
/*ARGSUSED*/
static int
{
/*
* since we preallocated, above, this shouldn't happen
*/
backend_panic("unexpected database change");
}
return (BACKEND_CALLBACK_CONTINUE);
}
/*ARGSUSED*/
void
{
}
/*ARGSUSED*/
static int
{
const char *name;
const char *cur;
int rc;
/*
* fill in the values, if any
*/
backend_query_t *q = backend_query_alloc();
/*
* Ensure that select operation is reflective
* of repository schema. If the repository has
* been upgraded, make use of value ordering
* by retrieving values in order using the
* value_order column. Otherwise, simply
* run the select with no order specified.
* The order-insensitive select is necessary
* as on first reboot post-upgrade, the repository
* contents need to be read before the repository
* backend is writable (and upgrade is possible).
*/
if (backend_is_upgraded(tx)) {
"SELECT value_value FROM value_tbl "
"WHERE (value_id = '%q') ORDER BY value_order",
cur);
} else {
"SELECT value_value FROM value_tbl "
"WHERE (value_id = '%q')",
cur);
}
&info)) {
case REP_PROTOCOL_SUCCESS:
break;
return (BACKEND_CALLBACK_ABORT);
case REP_PROTOCOL_DONE:
default:
backend_panic("backend_tx_run() returned %d", r);
}
return (BACKEND_CALLBACK_ABORT);
}
&info)) {
case REP_PROTOCOL_SUCCESS:
break;
return (BACKEND_CALLBACK_ABORT);
case REP_PROTOCOL_DONE:
default:
backend_panic("backend_tx_run() returned %d",
r);
}
}
}
if (rc != REP_PROTOCOL_SUCCESS) {
return (BACKEND_CALLBACK_ABORT);
}
return (BACKEND_CALLBACK_CONTINUE);
}
/*
* The *_setup_child_info() functions fill in a child_info_t structure with the
* information for the children of np with type type.
*
* They fail with
* _TYPE_MISMATCH - object cannot have children of type type
*/
static int
{
if (type != REP_PROTOCOL_ENTITY_SERVICE)
return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
return (REP_PROTOCOL_SUCCESS);
}
static int
{
switch (type) {
break;
default:
return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
}
return (REP_PROTOCOL_SUCCESS);
}
static int
{
switch (type) {
break;
default:
return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
}
return (REP_PROTOCOL_SUCCESS);
}
static int
{
if (type != REP_PROTOCOL_ENTITY_PROPERTYGRP)
return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
return (REP_PROTOCOL_SUCCESS);
}
static int
{
if (type != REP_PROTOCOL_ENTITY_PROPERTY)
return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
return (REP_PROTOCOL_SUCCESS);
}
/*
* The *_fill_children() functions populate the children of the given rc_node_t
* by querying the database and calling rc_node_setup_*() functions (usually
* via a fill_*_callback()).
*
* They fail with
* _NO_RESOURCES
*/
/*
* Returns
* _NO_RESOURCES
* _SUCCESS
*/
static int
{
backend_query_t *q;
int res;
q = backend_query_alloc();
backend_query_append(q, "SELECT svc_name, svc_id FROM service_tbl");
if (res == REP_PROTOCOL_DONE)
return (res);
}
/*
* Returns
* _NO_RESOURCES
* _SUCCESS
*/
static int
{
backend_query_t *q;
int res;
q = backend_query_alloc();
"SELECT instance_name, instance_id FROM instance_tbl"
" WHERE (instance_svc = %d)",
if (res == REP_PROTOCOL_DONE)
if (res != REP_PROTOCOL_SUCCESS)
return (res);
&ci);
q = backend_query_alloc();
"SELECT pg_name, pg_id, pg_gen_id, pg_type, pg_flags FROM pg_tbl"
" WHERE (pg_parent_id = %d)",
if (res == REP_PROTOCOL_SUCCESS) {
fill_pg_callback, &ci);
/* nonpersistant database may not exist */
if (res == REP_PROTOCOL_FAIL_BACKEND_ACCESS)
}
if (res == REP_PROTOCOL_DONE)
return (res);
}
/*
* Returns
* _NO_RESOURCES
* _SUCCESS
*/
static int
{
backend_query_t *q;
int res;
/* Get child property groups */
&ci);
q = backend_query_alloc();
"SELECT pg_name, pg_id, pg_gen_id, pg_type, pg_flags FROM pg_tbl"
" WHERE (pg_parent_id = %d)",
if (res == REP_PROTOCOL_SUCCESS) {
fill_pg_callback, &ci);
/* nonpersistant database may not exist */
if (res == REP_PROTOCOL_FAIL_BACKEND_ACCESS)
}
if (res == REP_PROTOCOL_DONE)
if (res != REP_PROTOCOL_SUCCESS)
return (res);
/* Get child snapshots */
&ci);
q = backend_query_alloc();
"SELECT lnk_snap_name, lnk_id, lnk_snap_id FROM snapshot_lnk_tbl"
" WHERE (lnk_inst_id = %d)",
if (res == REP_PROTOCOL_DONE)
return (res);
}
/*
* Returns
* _NO_RESOURCES
* _SUCCESS
*/
static int
{
int r;
/* Get the rc_snapshot_t (& its rc_snaplevel_t's). */
if (r != REP_PROTOCOL_SUCCESS) {
return (r);
}
}
/* Create rc_node_t's for the snapshot's rc_snaplevel_t's. */
nnp = rc_node_alloc();
}
return (REP_PROTOCOL_SUCCESS);
}
/*
* Returns
* _NO_RESOURCES
* _SUCCESS
*/
static int
{
int res;
backend_query_t *q;
&ci);
q = backend_query_alloc();
"SELECT snaplvl_pg_name, snaplvl_pg_id, snaplvl_gen_id, "
" snaplvl_pg_type, snaplvl_pg_flags "
" FROM snaplevel_lnk_tbl "
" WHERE (snaplvl_level_id = %d)",
lvl->rsl_level_id);
if (res == REP_PROTOCOL_DONE)
return (res);
}
/*
* Returns
* _NO_RESOURCES
* _SUCCESS
*/
static int
{
backend_query_t *q;
int res;
&ci);
if (res != REP_PROTOCOL_SUCCESS) {
/*
* If the backend didn't exist, we wouldn't have got this
* property group.
*/
return (res);
}
q = backend_query_alloc();
"SELECT lnk_prop_name, lnk_prop_id, lnk_prop_type, lnk_val_id "
"FROM prop_lnk_tbl "
"WHERE (lnk_pg_id = %d AND lnk_gen_id = %d)",
if (res == REP_PROTOCOL_DONE)
return (res);
}
/*
* Fails with
* _TYPE_MISMATCH - lp is not for a service
* _INVALID_TYPE - lp has invalid type
* _BAD_REQUEST - name is invalid
*/
static int
{
int rc;
if (type != REP_PROTOCOL_ENTITY_SERVICE)
return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
return (rc);
"SELECT svc_id FROM service_tbl "
"WHERE svc_name = '%q'",
name);
return (REP_PROTOCOL_SUCCESS);
}
/*
* Fails with
* _NO_RESOURCES - out of memory
*/
static int
{
return (backend_tx_run_update(tx,
"INSERT INTO service_tbl (svc_id, svc_name) "
"VALUES (%d, '%q')",
}
/*
* Fails with
* _TYPE_MISMATCH - lp is not for an instance or property group
* _INVALID_TYPE - lp has invalid type
* _BAD_REQUEST - name is invalid
*/
static int
{
int rc;
if (type != REP_PROTOCOL_ENTITY_INSTANCE &&
return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
return (rc);
switch (type) {
"SELECT instance_id FROM instance_tbl "
"WHERE instance_name = '%q' AND instance_svc = %d",
break;
"SELECT pg_id FROM pg_tbl "
" WHERE pg_name = '%q' AND pg_parent_id = %d",
break;
default:
assert(0);
abort();
}
return (REP_PROTOCOL_SUCCESS);
}
/*
* Fails with
* _NO_RESOURCES - out of memory
*/
static int
{
return (backend_tx_run_update(tx,
"INSERT INTO instance_tbl "
" (instance_id, instance_name, instance_svc) "
"VALUES (%d, '%q', %d)",
}
/*
* Fails with
* _NO_RESOURCES - out of memory
*/
static int
{
return (backend_tx_run_update(tx,
"INSERT INTO snapshot_lnk_tbl "
" (lnk_id, lnk_inst_id, lnk_snap_name, lnk_snap_id) "
"VALUES (%d, %d, '%q', 0)",
}
/*
* Fails with
* _TYPE_MISMATCH - lp is not for a property group or snapshot
* _INVALID_TYPE - lp has invalid type
* _BAD_REQUEST - name is invalid
*/
static int
{
int rc;
if (type != REP_PROTOCOL_ENTITY_PROPERTYGRP &&
return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
return (rc);
switch (type) {
"SELECT pg_id FROM pg_tbl "
" WHERE pg_name = '%q' AND pg_parent_id = %d",
break;
"SELECT lnk_id FROM snapshot_lnk_tbl "
" WHERE lnk_snap_name = '%q' AND lnk_inst_id = %d",
break;
default:
assert(0);
abort();
}
return (REP_PROTOCOL_SUCCESS);
}
static int
{
return (backend_tx_run_update(tx,
"INSERT INTO pg_tbl "
" (pg_id, pg_name, pg_parent_id, pg_type, pg_flags, pg_gen_id) "
"VALUES (%d, '%q', %d, '%q', %d, %d)",
}
static int
{
int r;
backend_query_t *q = backend_query_alloc();
/*
* Check for child instances, and refuse to delete if they exist.
*/
"SELECT 1 FROM instance_tbl WHERE instance_svc = %d",
if (r == REP_PROTOCOL_DONE)
return (REP_PROTOCOL_FAIL_EXISTS); /* instances exist */
}
static int
{
}
static int
{
}
static int
{
}
NULL,
NULL,
},
},
},
NULL,
NULL,
NULL,
NULL,
},
},
NULL,
NULL,
NULL,
NULL,
},
{-1UL}
};
/*
* object_fill_children() populates the child list of an rc_node_t by calling
* the appropriate <type>_fill_children() which runs backend queries that
* call an appropriate fill_*_callback() which takes a row of results,
* decodes them, and calls an rc_node_setup*() function in rc_node.c to create
* a child.
*
* Fails with
* _NO_RESOURCES
*/
int
{
}
int
{
int rc;
return (REP_PROTOCOL_FAIL_BAD_REQUEST);
if (rc != REP_PROTOCOL_SUCCESS)
return (rc);
if (rc == REP_PROTOCOL_FAIL_BACKEND_ACCESS ||
else if (rc != REP_PROTOCOL_SUCCESS) {
return (rc);
}
goto fail;
}
if (rc != REP_PROTOCOL_SUCCESS)
goto fail;
}
if (rc != REP_PROTOCOL_SUCCESS)
return (rc);
fail:
return (rc);
}
int
{
backend_query_t *q;
int rc;
if (type == REP_PROTOCOL_ENTITY_PROPERTYGRP)
return (REP_PROTOCOL_FAIL_NOT_APPLICABLE);
return (REP_PROTOCOL_FAIL_BAD_REQUEST);
return (rc);
q = backend_query_alloc();
return (rc);
}
if (rc == REP_PROTOCOL_SUCCESS)
return (REP_PROTOCOL_FAIL_EXISTS);
else if (rc != REP_PROTOCOL_FAIL_NOT_FOUND)
return (rc);
return (REP_PROTOCOL_FAIL_NO_RESOURCES);
}
return (REP_PROTOCOL_FAIL_NO_RESOURCES);
return (rc);
}
return (REP_PROTOCOL_SUCCESS);
}
/*
* Fails with
* _NOT_APPLICABLE - type is _PROPERTYGRP
* _BAD_REQUEST - cannot create children for this type of node
* name is invalid
* _TYPE_MISMATCH - object cannot have children of type type
* _NO_RESOURCES - out of memory, or could not allocate new id
* _BACKEND_READONLY
* _BACKEND_ACCESS
* _EXISTS - child already exists
*/
int
{
int rc;
return (rc);
}
return (rc);
}
if (rc != REP_PROTOCOL_SUCCESS) {
return (rc);
}
return (REP_PROTOCOL_SUCCESS);
}
/*ARGSUSED*/
int
{
backend_query_t *q;
int rc;
int rc_wr;
int rc_ro;
if (ptype != REP_PROTOCOL_ENTITY_SERVICE &&
return (REP_PROTOCOL_FAIL_BAD_REQUEST);
return (rc);
q = backend_query_alloc();
return (rc);
}
if (!nonpersist) {
} else {
}
if (rc_wr != REP_PROTOCOL_SUCCESS) {
goto fail;
}
if (rc_ro != REP_PROTOCOL_SUCCESS &&
goto fail;
}
if (rc == REP_PROTOCOL_SUCCESS) {
goto fail;
} else if (rc != REP_PROTOCOL_FAIL_NOT_FOUND) {
goto fail;
}
}
if (rc == REP_PROTOCOL_SUCCESS) {
goto fail;
} else if (rc != REP_PROTOCOL_FAIL_NOT_FOUND) {
goto fail;
}
goto fail;
}
goto fail;
}
gen)) != REP_PROTOCOL_SUCCESS) {
goto fail;
}
if (rc != REP_PROTOCOL_SUCCESS) {
return (rc);
}
return (REP_PROTOCOL_SUCCESS);
fail:
return (rc);
}
/*
* Given a row of snaplevel number, snaplevel id, service id, service name,
* instance id, & instance name, create a rc_snaplevel_t & prepend it onto the
* rs_levels list of the rc_snapshot_t passed in as data.
* Returns _CONTINUE on success or _ABORT if any allocations fail.
*/
/*ARGSUSED*/
static int
{
return (BACKEND_CALLBACK_ABORT);
if (instance_id != NULL)
"snap_level_instance_id");
return (BACKEND_CALLBACK_ABORT);
}
if (instance) {
return (BACKEND_CALLBACK_ABORT);
}
} else {
}
return (BACKEND_CALLBACK_CONTINUE);
}
/*
* Populate sp's rs_levels list from the snaplevel_tbl table.
* Fails with
* _NO_RESOURCES
*/
int
{
backend_query_t *q;
int result;
int i;
q = backend_query_alloc();
"SELECT snap_level_num, snap_level_id, "
" snap_level_service_id, snap_level_service, "
" snap_level_instance_id, snap_level_instance "
"FROM snaplevel_tbl "
"WHERE snap_id = %d "
"ORDER BY snap_level_id DESC",
sp->rs_snap_id);
if (result == REP_PROTOCOL_DONE)
if (result == REP_PROTOCOL_SUCCESS) {
i = 0;
if (sl->rsl_level_num != ++i) {
backend_panic("snaplevels corrupt; expected "
}
}
}
return (result);
}
/*
* This represents a property group in a snapshot.
*/
typedef struct check_snapshot_elem {
char cse_seen;
typedef struct check_snapshot_info {
/*ARGSUSED*/
static int
{
const char *parent;
const char *pg_id;
const char *pg_gen_id;
if (columns == 1) {
backend_panic("snaplevel table has too many elements");
return (BACKEND_CALLBACK_CONTINUE);
}
return (BACKEND_CALLBACK_ABORT);
}
return (BACKEND_CALLBACK_CONTINUE);
}
static int
{
return (-1);
return (1);
return (-1);
return (1);
return (-1);
return (1);
return (0);
}
/*ARGSUSED*/
static int
{
return (BACKEND_CALLBACK_ABORT);
backend_panic("duplicate property group reported");
return (BACKEND_CALLBACK_CONTINUE);
}
/*
* Check that a snapshot matches up with the latest in the repository.
* Returns:
* REP_PROTOCOL_SUCCESS if it is up-to-date,
* REP_PROTOCOL_DONE if it is out-of-date, or
* REP_PROTOCOL_FAIL_NO_RESOURCES if we ran out of memory.
*/
static int
{
backend_query_t *q;
int result;
/* if the snapshot has never been taken, it must be out of date. */
if (snap_id == 0)
return (REP_PROTOCOL_DONE);
q = backend_query_alloc();
"SELECT\n"
" CASE snap_level_instance_id\n"
" WHEN 0 THEN snap_level_service_id\n"
" ELSE snap_level_instance_id\n"
" END\n"
"FROM snaplevel_tbl\n"
"WHERE snap_id = %d;\n"
"\n"
"SELECT\n"
" CASE snap_level_instance_id\n"
" WHEN 0 THEN snap_level_service_id\n"
" ELSE snap_level_instance_id\n"
" END,\n"
" snaplvl_pg_id,\n"
" snaplvl_gen_id\n"
"FROM snaplevel_tbl, snaplevel_lnk_tbl\n"
"WHERE\n"
" (snaplvl_level_id = snap_level_id AND\n"
" snap_id = %d);",
&csi);
if (result == REP_PROTOCOL_DONE)
if (result != REP_PROTOCOL_SUCCESS)
goto fail;
}
#if COMPOSITION_DEPTH == 2
goto fail;
}
q = backend_query_alloc();
"SELECT "
" pg_parent_id, pg_id, pg_gen_id "
"FROM "
" pg_tbl "
"WHERE (pg_parent_id = %d OR pg_parent_id = %d)",
&csi);
#else
#endif
/*
* To succeed, the callback must not have aborted, and we must have
* found all of the items.
*/
if (result == REP_PROTOCOL_SUCCESS) {
goto fail;
}
}
}
fail:
return (result);
}
/*ARGSUSED*/
static int
{
return (BACKEND_CALLBACK_ABORT);
}
return (BACKEND_CALLBACK_CONTINUE);
}
struct snaplevel_add_info {
};
/*ARGSUSED*/
static int
char **names)
{
"INSERT INTO snaplevel_lnk_tbl "
" (snaplvl_level_id, snaplvl_pg_id, snaplvl_pg_name, "
" snaplvl_pg_type, snaplvl_pg_flags, snaplvl_gen_id)"
"VALUES (%d, %s, '%q', '%q', %s, %s);",
return (BACKEND_CALLBACK_CONTINUE);
}
/*ARGSUSED*/
static int
{
backend_query_t *q;
int result;
if (data.sai_level_id == 0) {
return (REP_PROTOCOL_FAIL_NO_RESOURCES);
}
"INSERT INTO snaplevel_tbl "
" (snap_id, snap_level_num, snap_level_id, "
" snap_level_service_id, snap_level_service, "
" snap_level_instance_id, snap_level_instance) "
"VALUES (%d, %d, %d, %d, %Q, %d, %Q);",
q = backend_query_alloc();
"SELECT pg_id, pg_name, pg_type, pg_flags, pg_gen_id FROM pg_tbl "
"WHERE (pg_parent_id = %d);",
&data);
return (result);
}
/*
* Fails with:
* _NO_RESOURCES - no new id or out of disk space
* _BACKEND_READONLY - persistent backend is read-only
*/
static int
{
backend_query_t *q;
int result;
if (result != REP_PROTOCOL_SUCCESS)
return (result);
if (snapid == 0) {
goto fail;
}
q = backend_query_alloc();
"SELECT svc_name FROM service_tbl "
"WHERE (svc_id = %d)", svcid);
if (result == REP_PROTOCOL_DONE) {
goto fail;
}
backend_panic("unable to find name for svc id %d\n",
svcid);
if (result != REP_PROTOCOL_SUCCESS)
goto fail;
}
q = backend_query_alloc();
"SELECT instance_name FROM instance_tbl "
"WHERE (instance_id = %d)", instid);
if (result == REP_PROTOCOL_DONE) {
goto fail;
}
"unable to find name for instance id %d\n", instid);
if (result != REP_PROTOCOL_SUCCESS)
goto fail;
}
if (result != REP_PROTOCOL_SUCCESS)
goto fail;
if (result != REP_PROTOCOL_SUCCESS)
goto fail;
*snapid_out = snapid;
return (REP_PROTOCOL_SUCCESS);
fail:
return (result);
}
/*
* Fails with:
* _TYPE_MISMATCH - pp is not an instance
* _NO_RESOURCES - no new id or out of disk space
* _BACKEND_READONLY - persistent backend is read-only
*/
int
{
int result;
return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
if (result != REP_PROTOCOL_SUCCESS)
return (result);
return (result);
}
/*
* link the new object to the new snapshot.
*/
"UPDATE snapshot_lnk_tbl SET lnk_snap_id = %d WHERE lnk_id = %d;",
if (result != REP_PROTOCOL_SUCCESS) {
return (result);
}
if (result != REP_PROTOCOL_SUCCESS) {
return (result);
}
return (REP_PROTOCOL_SUCCESS);
}
/*
* Fails with:
* _TYPE_MISMATCH - pp is not an instance
* _NO_RESOURCES - no new id or out of disk space
* _BACKEND_READONLY - persistent backend is read-only
*/
int
int takesnap)
{
backend_query_t *q;
int result;
return (REP_PROTOCOL_FAIL_TYPE_MISMATCH);
if (takesnap) {
/* first, check that we're actually out of date */
return (REP_PROTOCOL_SUCCESS);
if (result != REP_PROTOCOL_SUCCESS)
return (result);
} else {
if (result != REP_PROTOCOL_SUCCESS)
return (result);
}
q = backend_query_alloc();
"SELECT lnk_snap_id FROM snapshot_lnk_tbl WHERE lnk_id = %d; "
"UPDATE snapshot_lnk_tbl SET lnk_snap_id = %d WHERE lnk_id = %d;",
if (result == REP_PROTOCOL_FAIL_NOT_FOUND) {
backend_panic("unable to find snapshot id %d",
snapi->rl_main_id);
}
if (result != REP_PROTOCOL_SUCCESS)
goto fail;
/*
* Now we use the delete stack to handle the possible unreferencing
* of oldsnapid.
*/
goto fail;
if (result != REP_PROTOCOL_SUCCESS)
goto fail;
}
if (result != REP_PROTOCOL_SUCCESS)
goto fail;
*snapid_ptr = snapid;
return (REP_PROTOCOL_SUCCESS);
fail:
return (result);
}