mm_sql.c revision cee0fb94c0d4227de0a00efc162fb2739844b641
/*
* 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
* or http://www.opensolaris.org/os/licensing.
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <syslog.h>
#include <mms_list.h>
#include <mms_parser.h>
#include <mms_par_impl.h>
#include <libpq-fe.h>
#include <mms_trace.h>
#include <mms_strapp.h>
#include <pthread.h>
#include "mm_db.h"
#include "mm.h"
#include "mm_util.h"
#include "mm_commands.h"
#include "mm_sql.h"
#include "mm_sql_impl.h"
#include "mm_path.h"
static char *_SrcFile = __FILE__;
extern mm_pkey_t *mm_get_pkey(char *obj);
char *mm_sql_number_buf(mm_command_t *cmd);
char *mm_sql_order_buf(mm_command_t *cmd);
static sql_ops_tab_t opstab[] = {
"strlohi", "ASC",
"strhilo", "DESC",
"numlohi", "ASC",
"numhilo", "DESC",
"regex", "~",
"streq", "=",
"strne", "<>",
"strlt", "<",
"strle", "<=",
"strgt", ">",
"strge", ">=",
"numeq", "=",
"numne", "<>",
"numlt", "<",
"numle", "<=",
"numgt", ">",
"numge", ">=",
"and", "AND",
"or", "OR",
"not", "NOT",
"hosteq", "=",
"hostne", "<>"
};
static int num_ops = sizeof (opstab) / sizeof (sql_ops_tab_t);
char *
mm_get_cart_pcl(mm_command_t *cmd, char *cart_id, mm_db_t *db)
{
char *value;
char *cart_pcl;
/*
* Get cartridge pcl from cartridge id
*/
if (cart_id == NULL) {
mms_trace(MMS_DEVP, "cartridge id is null");
SQL_CHK_LEN(&cmd->cmd_buf, 0, &cmd->cmd_bufsize,
strlen(RESPONSE_ERROR) + strlen(cmd->cmd_task) +
strlen(ECLASS_EXPLICIT) + strlen(ENOMATCH) + 1);
(void) snprintf(cmd->cmd_buf, cmd->cmd_bufsize,
RESPONSE_ERROR, cmd->cmd_task,
ECLASS_EXPLICIT, ENOMATCH);
return (NULL);
}
if (mm_db_exec(HERE, db, "select \"CartridgePCL\" from \"CARTRIDGE\" "
"where \"CartridgeID\" = '%s'", cart_id) != MM_DB_DATA) {
mm_clear_db(&db->mm_db_results);
SQL_CHK_LEN(&cmd->cmd_buf, 0, &cmd->cmd_bufsize,
strlen(RESPONSE_ERROR) + strlen(cmd->cmd_task) +
strlen(ECLASS_INTERNAL) + strlen(EDATABASE) + 1);
(void) snprintf(cmd->cmd_buf, cmd->cmd_bufsize,
RESPONSE_ERROR, cmd->cmd_task,
ECLASS_INTERNAL, EDATABASE);
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
return (NULL);
}
if (PQntuples(db->mm_db_results) != 1) {
mms_trace(MMS_DEVP, "cartridge pcl failed");
SQL_CHK_LEN(&cmd->cmd_buf, 0, &cmd->cmd_bufsize,
strlen(RESPONSE_ERROR) + strlen(cmd->cmd_task) +
strlen(ECLASS_EXPLICIT) + strlen(ENOMATCH) + 1);
(void) snprintf(cmd->cmd_buf, cmd->cmd_bufsize,
RESPONSE_ERROR, cmd->cmd_task,
ECLASS_EXPLICIT, ENOMATCH);
mm_clear_db(&db->mm_db_results);
return (NULL);
}
value = PQgetvalue(db->mm_db_results, 0, 0);
if (value[0] == '\0') {
value = "none";
}
cart_pcl = strdup(value);
mm_clear_db(&db->mm_db_results);
if (cart_pcl == NULL) {
no_mem:
MM_ABORT_NO_MEM();
}
return (cart_pcl);
}
int
mm_set_cartridge_status(char *id, char *status, mm_db_t *db) {
if ((id == NULL) ||
(status == NULL)) {
mms_trace(MMS_ERR,
"id and/or status cannot be null");
return (1);
}
/* Allowed values for status are : */
/* in use */
/* unavailable */
/* available */
if (mm_db_exec(HERE, db,
"update \"CARTRIDGE\" "
"set \"CartridgeStatus\" = '%s' "
"where \"CartridgeID\" = '%s';",
status, id) != MM_DB_OK) {
mms_trace(MMS_ERR,
"Error updateing cartridge state, %s, %s",
id, status);
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
return (1);
}
return (0);
}
int
mm_set_drive_statesoft(char *drive, char *state, mm_db_t *db) {
if ((drive == NULL) ||
(state == NULL)) {
mms_trace(MMS_ERR,
"drive and/or state cannot be null");
return (1);
}
/* Allowed values for status are : */
/* in use */
/* ready */
if (mm_db_exec(HERE, db,
"update \"DRIVE\" "
"set \"DriveStateSoft\" = '%s' "
"where \"DriveName\" = '%s';",
state, drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"Error updateing drive state, %s, %s",
drive, state);
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
return (1);
}
return (0);
}
void
mm_set_mount_info_cart(char *cart_id,
cmd_mount_info_t *mount_info) {
if (mount_info->cmi_cartridge)
free(mount_info->cmi_cartridge);
mount_info->cmi_cartridge = NULL;
mount_info->cmi_cartridge =
mms_strapp(mount_info->cmi_cartridge,
cart_id);
}
void
mm_set_mount_info_drive(char *drive,
cmd_mount_info_t *mount_info) {
if (mount_info->cmi_drive)
free(mount_info->cmi_drive);
mount_info->cmi_drive = NULL;
mount_info->cmi_drive =
mms_strapp(mount_info->cmi_drive,
drive);
}
void
mm_set_mount_info_library(char *library,
cmd_mount_info_t *mount_info) {
if (mount_info->cmi_library)
free(mount_info->cmi_library);
mount_info->cmi_library = NULL;
mount_info->cmi_library =
mms_strapp(mount_info->cmi_library,
library);
}
void
mm_set_mount_info_dm(char *dm,
cmd_mount_info_t *mount_info) {
if (mount_info->cmi_dm)
free(mount_info->cmi_dm);
mount_info->cmi_dm = NULL;
mount_info->cmi_dm =
mms_strapp(mount_info->cmi_dm,
dm);
}
void
mm_set_mount_info_pcl(char *pcl,
cmd_mount_info_t *mount_info) {
if (mount_info->cmi_pcl)
free(mount_info->cmi_pcl);
mount_info->cmi_pcl = NULL;
mount_info->cmi_pcl =
mms_strapp(mount_info->cmi_pcl,
pcl);
}
void
mm_free_mount_info(cmd_mount_info_t *mount_info) {
if (mount_info->cmi_cartridge)
free(mount_info->cmi_cartridge);
if (mount_info->cmi_drive)
free(mount_info->cmi_drive);
if (mount_info->cmi_library)
free(mount_info->cmi_library);
if (mount_info->cmi_dm)
free(mount_info->cmi_dm);
if (mount_info->cmi_pcl)
free(mount_info->cmi_pcl);
mount_info->cmi_cartridge = NULL;
mount_info->cmi_pcl = NULL;
mount_info->cmi_drive = NULL;
mount_info->cmi_library = NULL;
mount_info->cmi_dm = NULL;
}
void
mm_print_dm_status(mm_dm_stat_t *dm_stat) {
mms_trace(MMS_DEVP,
"DM, %s, Status for Drive, %s, host, %s",
dm_stat->dm_stat_name,
dm_stat->dm_stat_drive,
dm_stat->dm_stat_host);
mms_trace(MMS_DEVP,
" DMStateHard = %s",
dm_stat->dm_stat_hard);
mms_trace(MMS_DEVP,
" DMStateSoft = %s",
dm_stat->dm_stat_soft);
mms_trace(MMS_DEVP,
" DMDisabled = %s",
dm_stat->dm_stat_disabled);
}
void
mm_free_dm_status(mm_dm_stat_t *dm_stat) {
if (dm_stat == NULL) {
return;
}
if (dm_stat->dm_stat_name)
free(dm_stat->dm_stat_name);
if (dm_stat->dm_stat_hard)
free(dm_stat->dm_stat_hard);
if (dm_stat->dm_stat_disabled)
free(dm_stat->dm_stat_disabled);
if (dm_stat->dm_stat_soft)
free(dm_stat->dm_stat_soft);
if (dm_stat->dm_stat_host)
free(dm_stat->dm_stat_host);
if (dm_stat->dm_stat_drive)
free(dm_stat->dm_stat_drive);
free(dm_stat);
}
mm_dm_stat_t *
mm_get_dm_status(char *dm_name, char *drive_name, char *host, mm_db_t *db) {
mm_dm_stat_t *dm_status = NULL;
char *cmd_buf = NULL;
/* when dm name is null, use drive and host to return the dm status */
cmd_buf = mms_strapp(cmd_buf,
"select "
"\"DM\".\"DMStateHard\", "
"\"DM\".\"DMStateSoft\", "
"\"DM\".\"DriveName\", "
"\"DM\".\"DMDisabled\", "
"\"DM\".\"DMTargetHost\", "
"\"DM\".\"DMName\" "
"from \"DM\" ");
if (dm_name == NULL) {
if ((drive_name == NULL) ||
(host == NULL)) {
mms_trace(MMS_ERR,
"need drive and host if dm namd is null",
", mm_get_dm_status");
free(cmd_buf);
return (NULL);
}
/* use drive/host constraint */
cmd_buf = mms_strapp(cmd_buf,
"where \"DriveName\" = '%s' "
"and pg_host_ident(\"DMTargetHost\") "
"= pg_host_ident('%s');",
drive_name,
host);
} else {
/* use dm name constrant */
cmd_buf = mms_strapp(cmd_buf,
"where \"DM\".\"DMName\" = '%s'",
dm_name);
}
if (mm_db_exec(HERE, db, cmd_buf) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"db error, mm_get_dm_status");
free(cmd_buf);
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
return (NULL);
}
free(cmd_buf);
if (PQntuples(db->mm_db_results) != 1) {
mms_trace(MMS_ERR,
"row num mismatch, "
"mm_get_drive_status");
mm_clear_db(&db->mm_db_results);
return (NULL);
}
dm_status = (mm_dm_stat_t *)calloc(1, sizeof (mm_dm_stat_t));
if (dm_status == NULL) {
mms_trace(MMS_ERR,
"Unable to malloc dm_status");
mm_clear_db(&db->mm_db_results);
return (NULL);
}
dm_status->dm_stat_hard = mms_strapp(dm_status->dm_stat_hard,
PQgetvalue(db->mm_db_results, 0, 0));
dm_status->dm_stat_soft = mms_strapp(dm_status->dm_stat_soft,
PQgetvalue(db->mm_db_results, 0, 1));
dm_status->dm_stat_drive = mms_strapp(dm_status->dm_stat_drive,
PQgetvalue(db->mm_db_results, 0, 2));
dm_status->dm_stat_disabled = mms_strapp(dm_status->dm_stat_disabled,
PQgetvalue(db->mm_db_results, 0, 3));
dm_status->dm_stat_host = mms_strapp(dm_status->dm_stat_host,
PQgetvalue(db->mm_db_results, 0, 4));
dm_status->dm_stat_name = mms_strapp(dm_status->dm_stat_name,
PQgetvalue(db->mm_db_results, 0, 5));
mm_clear_db(&db->mm_db_results);
return (dm_status);
}
void
mm_print_drive_status(mm_drive_stat_t *drive_stat) {
mms_trace(MMS_DEVP,
"Drive Status for Drive, %s",
drive_stat->drive_stat_name);
mms_trace(MMS_DEVP,
" DriveDisabled = %s",
drive_stat->drive_stat_disabled);
mms_trace(MMS_DEVP,
" DriveBroken = %s",
drive_stat->drive_stat_broken);
mms_trace(MMS_DEVP,
" DriveStateSoft = %s",
drive_stat->drive_stat_soft);
mms_trace(MMS_DEVP,
" DriveStateHard = %s",
drive_stat->drive_stat_hard);
mms_trace(MMS_DEVP,
" DriveLibraryAccessible = %s",
drive_stat->drive_stat_lib_acc);
mms_trace(MMS_DEVP,
" ExclusiveAppName = %s",
drive_stat->drive_stat_excl_app);
mms_trace(MMS_DEVP,
" DriveOnline = %s",
drive_stat->drive_stat_online);
mms_trace(MMS_DEVP,
" DriveGroupName = %s",
drive_stat->drive_stat_group);
mms_trace(MMS_DEVP,
" LibraryName = %s",
drive_stat->drive_stat_library);
mms_trace(MMS_DEVP,
" DrivePriority = %s",
drive_stat->drive_stat_priority);
mms_trace(MMS_DEVP,
" DMName = %s",
drive_stat->drive_stat_dm);
mms_trace(MMS_DEVP,
" DriveGeometry = %s",
drive_stat->drive_stat_geometry);
mms_trace(MMS_DEVP,
" DriveSerialNum = %s",
drive_stat->drive_stat_serial);
mms_trace(MMS_DEVP,
" CartridgePCL = %s",
drive_stat->drive_stat_pcl);
mms_trace(MMS_DEVP,
" DriveLibraryOccupied = %s",
drive_stat->drive_stat_drvlib_occ);
}
void
mm_free_drive_status(mm_drive_stat_t *drive_stat) {
if (drive_stat == NULL) {
return;
}
if (drive_stat->drive_stat_name)
free(drive_stat->drive_stat_name);
if (drive_stat->drive_stat_hard)
free(drive_stat->drive_stat_hard);
if (drive_stat->drive_stat_disabled)
free(drive_stat->drive_stat_disabled);
if (drive_stat->drive_stat_soft)
free(drive_stat->drive_stat_soft);
if (drive_stat->drive_stat_library)
free(drive_stat->drive_stat_library);
if (drive_stat->drive_stat_lib_acc)
free(drive_stat->drive_stat_lib_acc);
if (drive_stat->drive_stat_group)
free(drive_stat->drive_stat_group);
if (drive_stat->drive_stat_excl_app)
free(drive_stat->drive_stat_excl_app);
if (drive_stat->drive_stat_broken)
free(drive_stat->drive_stat_broken);
if (drive_stat->drive_stat_online)
free(drive_stat->drive_stat_online);
if (drive_stat->drive_stat_priority)
free(drive_stat->drive_stat_priority);
if (drive_stat->drive_stat_dm)
free(drive_stat->drive_stat_dm);
if (drive_stat->drive_stat_geometry)
free(drive_stat->drive_stat_geometry);
if (drive_stat->drive_stat_serial)
free(drive_stat->drive_stat_serial);
if (drive_stat->drive_stat_pcl)
free(drive_stat->drive_stat_pcl);
if (drive_stat->drive_stat_drvlib_occ)
free(drive_stat->drive_stat_drvlib_occ);
free(drive_stat);
}
mm_drive_stat_t *
mm_get_drive_status(char *drive_name, mm_db_t *db) {
mm_drive_stat_t *drive_status = NULL;
if (mm_db_exec(HERE, db,
"select "
"\"DRIVE\".\"DriveDisabled\", "
"\"DRIVE\".\"DriveBroken\", "
"\"DRIVE\".\"DriveStateSoft\", "
"\"DRIVE\".\"DriveLibraryAccessible\", "
"\"DRIVE\".\"ExclusiveAppName\", "
"\"DRIVE\".\"DriveOnline\", "
"\"DRIVE\".\"DriveGroupName\", "
"\"DRIVE\".\"DriveStateHard\", "
"\"DRIVE\".\"LibraryName\", "
"\"DRIVE\".\"DrivePriority\", "
"\"DRIVE\".\"DMName\", "
"\"DRIVE\".\"DriveGeometry\", "
"\"DRIVE\".\"DriveSerialNum\", "
"\"DRIVE\".\"CartridgePCL\", "
"\"DRIVE\".\"DriveLibraryOccupied\" "
"from \"DRIVE\" "
"where \"DriveName\" = '%s';",
drive_name) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"db error, mm_get_drive_status");
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
return (NULL);
}
if (PQntuples(db->mm_db_results) != 1) {
mms_trace(MMS_ERR,
"row num mismatch, "
"mm_get_drive_status");
mm_clear_db(&db->mm_db_results);
return (NULL);
}
drive_status = (mm_drive_stat_t *)calloc(1, sizeof (mm_drive_stat_t));
if (drive_status == NULL) {
mms_trace(MMS_ERR,
"Unable to malloc drive_status");
return (NULL);
}
drive_status->drive_stat_name =
mms_strapp(drive_status->drive_stat_name,
drive_name);
drive_status->drive_stat_disabled =
mms_strapp(drive_status->drive_stat_disabled,
PQgetvalue(db->mm_db_results, 0, 0));
drive_status->drive_stat_broken =
mms_strapp(drive_status->drive_stat_broken,
PQgetvalue(db->mm_db_results, 0, 1));
drive_status->drive_stat_soft =
mms_strapp(drive_status->drive_stat_soft,
PQgetvalue(db->mm_db_results, 0, 2));
drive_status->drive_stat_lib_acc =
mms_strapp(drive_status->drive_stat_lib_acc,
PQgetvalue(db->mm_db_results, 0, 3));
drive_status->drive_stat_excl_app =
mms_strapp(drive_status->drive_stat_excl_app,
PQgetvalue(db->mm_db_results, 0, 4));
drive_status->drive_stat_online =
mms_strapp(drive_status->drive_stat_online,
PQgetvalue(db->mm_db_results, 0, 5));
drive_status->drive_stat_group =
mms_strapp(drive_status->drive_stat_group,
PQgetvalue(db->mm_db_results, 0, 6));
drive_status->drive_stat_hard =
mms_strapp(drive_status->drive_stat_hard,
PQgetvalue(db->mm_db_results, 0, 7));
drive_status->drive_stat_library =
mms_strapp(drive_status->drive_stat_library,
PQgetvalue(db->mm_db_results, 0, 8));
drive_status->drive_stat_priority =
mms_strapp(drive_status->drive_stat_priority,
PQgetvalue(db->mm_db_results, 0, 9));
drive_status->drive_stat_dm =
mms_strapp(drive_status->drive_stat_dm,
PQgetvalue(db->mm_db_results, 0, 10));
drive_status->drive_stat_geometry =
mms_strapp(drive_status->drive_stat_geometry,
PQgetvalue(db->mm_db_results, 0, 11));
drive_status->drive_stat_serial =
mms_strapp(drive_status->drive_stat_serial,
PQgetvalue(db->mm_db_results, 0, 12));
drive_status->drive_stat_pcl =
mms_strapp(drive_status->drive_stat_pcl,
PQgetvalue(db->mm_db_results, 0, 13));
drive_status->drive_stat_drvlib_occ =
mms_strapp(drive_status->drive_stat_drvlib_occ,
PQgetvalue(db->mm_db_results, 0, 14));
mm_clear_db(&db->mm_db_results);
return (drive_status);
}
void
mm_print_lm_status(mm_lm_stat_t *lm_stat) {
mms_trace(MMS_DEVP,
"LM Status for LM, %s",
lm_stat->lm_stat_name);
mms_trace(MMS_DEVP,
" LibraryName = %s",
lm_stat->lm_stat_library);
mms_trace(MMS_DEVP,
" LMStateHard = %s",
lm_stat->lm_stat_hard);
mms_trace(MMS_DEVP,
" LMStateSoft = %s",
lm_stat->lm_stat_soft);
mms_trace(MMS_DEVP,
" LMDisabled = %s",
lm_stat->lm_stat_disabled);
}
void
mm_free_lm_status(mm_lm_stat_t *lm_stat) {
if (lm_stat == NULL) {
return;
}
if (lm_stat->lm_stat_name)
free(lm_stat->lm_stat_name);
if (lm_stat->lm_stat_hard)
free(lm_stat->lm_stat_hard);
if (lm_stat->lm_stat_disabled)
free(lm_stat->lm_stat_disabled);
if (lm_stat->lm_stat_soft)
free(lm_stat->lm_stat_soft);
if (lm_stat->lm_stat_library)
free(lm_stat->lm_stat_library);
free(lm_stat);
}
mm_lm_stat_t *
mm_get_lm_status(char *lm_name, mm_db_t *db) {
mm_lm_stat_t *lm_status = NULL;
if (mm_db_exec(HERE, db,
"select "
"\"LM\".\"LMStateHard\", "
"\"LM\".\"LMStateSoft\", "
"\"LM\".\"LMDisabled\", "
"\"LM\".\"LibraryName\" "
"from \"LM\" "
"where \"LMName\" = '%s';",
lm_name) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"db error, mm_get_lm_status");
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
return (NULL);
}
if (PQntuples(db->mm_db_results) != 1) {
mms_trace(MMS_ERR,
"row num mismatch, "
"mm_get_lm_status");
mm_clear_db(&db->mm_db_results);
return (NULL);
}
lm_status = (mm_lm_stat_t *)calloc(1, sizeof (mm_lm_stat_t));
if (lm_status == NULL) {
mms_trace(MMS_ERR,
"Unable to malloc lm_status");
return (NULL);
}
lm_status->lm_stat_name =
mms_strapp(lm_status->lm_stat_name,
lm_name);
lm_status->lm_stat_hard =
mms_strapp(lm_status->lm_stat_hard,
PQgetvalue(db->mm_db_results, 0, 0));
lm_status->lm_stat_soft =
mms_strapp(lm_status->lm_stat_soft,
PQgetvalue(db->mm_db_results, 0, 1));
lm_status->lm_stat_disabled =
mms_strapp(lm_status->lm_stat_disabled,
PQgetvalue(db->mm_db_results, 0, 2));
lm_status->lm_stat_library =
mms_strapp(lm_status->lm_stat_library,
PQgetvalue(db->mm_db_results, 0, 3));
mm_clear_db(&db->mm_db_results);
return (lm_status);
}
void
mm_print_library_status(mm_lib_stat_t *lib_stat) {
mms_trace(MMS_DEVP,
"Library Status for Library, %s",
lib_stat->lib_stat_name);
mms_trace(MMS_DEVP,
" LibraryOnline = %s",
lib_stat->lib_stat_online);
mms_trace(MMS_DEVP,
" LibraryDisabled = %s",
lib_stat->lib_stat_disabled);
mms_trace(MMS_DEVP,
" LibraryBroken = %s",
lib_stat->lib_stat_broken);
mms_trace(MMS_DEVP,
" LMName = %s",
lib_stat->lib_stat_lm);
}
void
mm_free_library_status(mm_lib_stat_t *lib_stat) {
if (lib_stat == NULL) {
return;
}
if (lib_stat->lib_stat_name)
free(lib_stat->lib_stat_name);
if (lib_stat->lib_stat_online)
free(lib_stat->lib_stat_online);
if (lib_stat->lib_stat_disabled)
free(lib_stat->lib_stat_disabled);
if (lib_stat->lib_stat_broken)
free(lib_stat->lib_stat_broken);
if (lib_stat->lib_stat_lm)
free(lib_stat->lib_stat_lm);
free(lib_stat);
}
mm_lib_stat_t *
mm_get_library_status(char *library_name, mm_db_t *db) {
mm_lib_stat_t *library_status = NULL;
if (mm_db_exec(HERE, db,
"select "
"\"LIBRARY\".\"LibraryOnline\", "
"\"LIBRARY\".\"LibraryDisabled\", "
"\"LIBRARY\".\"LibraryBroken\", "
"\"LIBRARY\".\"LMName\" "
"from \"LIBRARY\" "
"where \"LibraryName\" = '%s';",
library_name) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"db error, mm_get_library_status");
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
return (NULL);
}
if (PQntuples(db->mm_db_results) != 1) {
mms_trace(MMS_ERR,
"row num mismatch, "
"mm_get_library_status");
mm_clear_db(&db->mm_db_results);
return (NULL);
}
library_status = (mm_lib_stat_t *)calloc(1, sizeof (mm_lib_stat_t));
if (library_status == NULL) {
mms_trace(MMS_ERR,
"Unable to malloc library_status");
return (NULL);
}
library_status->lib_stat_name =
mms_strapp(library_status->lib_stat_name,
library_name);
library_status->lib_stat_online =
mms_strapp(library_status->lib_stat_online,
PQgetvalue(db->mm_db_results, 0, 0));
library_status->lib_stat_disabled =
mms_strapp(library_status->lib_stat_disabled,
PQgetvalue(db->mm_db_results, 0, 1));
library_status->lib_stat_broken =
mms_strapp(library_status->lib_stat_broken,
PQgetvalue(db->mm_db_results, 0, 2));
library_status->lib_stat_lm =
mms_strapp(library_status->lib_stat_lm,
PQgetvalue(db->mm_db_results, 0, 3));
mm_clear_db(&db->mm_db_results);
return (library_status);
}
static char *
mm_sql_get_ops(char *op)
{
int x;
for (x = 0; x < num_ops; x++) {
if (strcmp(opstab[x].sql_mmp_ops, op) == 0) {
return (opstab[x].sql_ops);
}
}
/* Not in table */
return ("??UNKNOWN??");
}
int
mm_sql_chk_len(char **line, int off, int *bufsize, int len)
{
char *new;
int new_bufsize;
if (off + len < *bufsize) {
return (0);
}
while (off + len > *bufsize) {
new_bufsize = *bufsize + SQL_CMD_BUF_INCR;
new = realloc(*line, new_bufsize);
if (new == NULL) {
return (-1);
}
*line = new;
*bufsize = new_bufsize;
}
return (0);
}
int
mm_notify_delete(mm_db_t *db, mm_command_t *cmd, char *objname,
int match_off)
{
PGresult *results;
int rows;
int row;
mms_trace(MMS_DEVP, "mm_notify_delete, object %s", objname);
/* get object instance */
if (mm_db_exec(HERE, db, "SELECT \"%sName\", \"%sTargetHost\""
" FROM \"%s\" %s", objname, objname,
objname, &cmd->cmd_buf[match_off]) != MM_DB_DATA) {
mm_sql_db_err_rsp_new(cmd, db);
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
return (MM_CMD_ERROR);
}
results = db->mm_db_results;
rows = PQntuples(results);
if (rows == 0) {
mms_trace(MMS_DEVP,
"Didn't match any %s's for delete", objname);
mm_clear_db(&db->mm_db_results);
return (INTRP_OK);
}
for (row = 0; row < rows; row ++) {
mms_trace(MMS_DEVP,
"notify object %s instance %s",
objname,
PQgetvalue(results, row, 0));
if (mm_notify_add_config(cmd->wka_ptr, cmd,
EVENT_CFG_DELETE,
objname,
PQgetvalue(results, row, 0),
PQgetvalue(results, row, 1))) {
mms_trace(MMS_ERR,
"mm_notify_delete: "
"error adding config event");
}
}
mm_clear_db(&db->mm_db_results);
return (INTRP_OK);
no_mem:
MM_ABORT_NO_MEM();
return (MM_CMD_ERROR);
}
int
mm_sql_notify_inst(mm_db_t *db, mm_command_t *cmd, char *objname,
int match_off, char **objinst)
{
PGresult *results = db->mm_db_results;
char *value;
mms_trace(MMS_DEVP, "sql notify inst, object %s", objname);
*objinst = NULL;
/* get object instance */
if (mm_db_exec(HERE, db, "SELECT \"%sName\" FROM \"%s\" %s", objname,
objname, &cmd->cmd_buf[match_off]) != MM_DB_DATA) {
mm_sql_db_err_rsp_new(cmd, db);
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
db->mm_db_results = results;
return (MM_CMD_ERROR);
}
if (PQntuples(db->mm_db_results) != 1) {
mm_clear_db(&db->mm_db_results);
db->mm_db_results = results;
return (INTRP_OK);
}
value = PQgetvalue(db->mm_db_results, 0, 0);
if (value[0] == '\0') {
*objinst = strdup("none"); /* none used for empty string */
} else {
*objinst = strdup(value);
}
mm_clear_db(&db->mm_db_results);
db->mm_db_results = results;
if (objinst == NULL) {
MM_ABORT("object instance");
return (MM_CMD_ERROR);
}
mms_trace(MMS_DEVP, "notify object %s instance %s", objname, *objinst);
return (INTRP_OK);
no_mem:
MM_ABORT_NO_MEM();
return (MM_CMD_ERROR);
}
void
mm_sql_report_write_value(char **buf, PGresult *results,
int row, int col, mm_command_t *cmd,
int reportmode) {
mm_db_t *db = &cmd->wka_ptr->mm_data->mm_db;
/* 3 possible reportmode formatting */
int name_rt = 1;
int value_rt = 2;
int namevalue_rt = 3;
Oid oid;
char *value;
char *name;
char date[24];
int i;
int len;
name = PQfname(results, col);
value = PQgetvalue(results, row, col);
oid = PQftype(results, col);
/* database data types to mms string conversions */
oid = PQftype(results, col);
if (oid == db->mm_db_cfg->mm_db_bool_oid) {
if (strcmp(value, "t") == 0) {
value = "true";
} else if (strcmp(value, "f") == 0) {
value = "false";
}
} else if (oid == db->mm_db_cfg->mm_db_timestamp_oid) {
if (strcmp(value, "-infinity") == 0) {
/* mms time not set */
value = "0000 00 00 00 00 00 000";
} else {
strcpy(date, value);
value = date;
/* mms UTC time format */
value[4] = ' '; /* - */
value[7] = ' '; /* - */
value[13] = ' '; /* : */
value[16] = ' '; /* : */
if (value[19] == '\0') {
value[20] = '\0';
}
value[19] = ' '; /* . */
len = strlen(value);
for (i = len; i < 23; i++) {
value[i] = '0';
}
value[23] = '\0';
}
}
if ((reportmode == name_rt) ||
(reportmode == namevalue_rt)) {
/* add name */
*(buf) = mms_strapp(*(buf),
" \"%s\"",
name);
}
if ((reportmode == value_rt) ||
(reportmode == namevalue_rt)) {
*(buf) = mms_strapp(*(buf), " \"%s\"", value);
}
return;
}
char *
mm_sql_report_attr(mm_command_t *cmd,
int row, int *col_count,
int num_atts, int reportmode,
PGresult *results) {
int col = *(col_count);
int start_col = *(col_count);
char *attr_buf = NULL;
int print = 0;
if (print)
mms_trace(MMS_DEVP,
"create attlist clause for row %d",
row);
/* print the attr list for row starting with col_count */
attr_buf = mms_strapp(attr_buf,
"attrlist[");
/* LINTED: */
for (col; col < (start_col + num_atts); col ++) {
mm_sql_report_write_value(&attr_buf,
results, row,
col, cmd,
reportmode);
}
attr_buf = mms_strapp(attr_buf,
"]");
*(col_count) = col;
return (attr_buf);
}
char *
mm_sql_report_text_row(mm_command_t *cmd,
int row, PGresult *results, int reportmode,
mms_list_t *format) {
mm_char_list_t *cur;
mm_char_list_t *next;
char *text_buf = NULL;
char *attr_buf = NULL;
int col_count = 0;
int print = 0;
/* Create the text clause for the report in cmd */
if (print)
mms_trace(MMS_DEVP,
"create text clause for row %d",
row);
/* First bracket for this text clause */
text_buf = mms_strapp(text_buf, "text[");
for (cur = mms_list_head(format);
cur != NULL;
cur = next) {
next = mms_list_next(format, cur);
if (cur->number == 0) {
/* Do data base format conversion */
/* The function will write into text buf */
mm_sql_report_write_value(&text_buf,
results, row,
col_count, cmd,
reportmode);
col_count ++;
} else {
/* This is an attrlist clause */
if ((attr_buf = mm_sql_report_attr(cmd,
row, &col_count,
cur->number, reportmode,
results)) == NULL) {
mms_trace(MMS_ERR,
"error setting atr_buf");
if (text_buf)
free(text_buf);
return (NULL);
}
text_buf = mms_strapp(text_buf, "%s",
attr_buf);
free(attr_buf);
}
}
/* Trailing bracket for this text text */
text_buf = mms_strapp(text_buf, "]");
return (text_buf);
}
int
mm_sql_format_report(mm_command_t *cmd, mms_par_node_t *report,
mms_list_t *format) {
mms_par_node_t *report_work;
mms_par_node_t *report_work_next;
mms_par_node_t *object;
mms_par_node_t *object_next;
/* 2 possible data types in report */
int data_type;
int obj_att = 1;
int att_list = 2;
char *cur_obj;
char *cur_attr;
int print = 0;
int num_atts = 0;
mm_db_t *db = &cmd->wka_ptr->mm_data->mm_db;
/* Create the text clause for the report in cmd */
if (print)
mms_trace(MMS_DEVP,
"determine formatting for this report");
data_type = 0;
/* Need to use attr list for OBJECTS */
report_work = NULL;
for (object = mms_pn_lookup(report, NULL, NULL, &report_work);
object != NULL;
object = mms_pn_lookup(report, NULL, NULL, &report_work)) {
if (object->pn_string != NULL) {
if (print)
mms_trace(MMS_DEVP,
"cur object is %s",
object->pn_string);
}
if (object->pn_type == MMS_PN_OBJ) {
/* determine if attr list is needed */
report_work_next = NULL;
report_work_next = report_work;
object_next = NULL;
object_next =
mms_pn_lookup(report, NULL, NULL,
&report_work_next);
if ((object_next != NULL) &&
(object_next->pn_type == MMS_PN_ATTR)) {
/* don't need an attrlist */
/* set the obj name */
/* The next object will be an attribute */
if (print)
mms_trace(MMS_DEVP,
"set obj for obj.attr, %s",
object->pn_string);
cur_obj = object->pn_string;
} else {
/* Need attr list */
/* Write all name/values for this obj */
if (print)
mms_trace(MMS_DEVP,
"set obj for attr list, %s",
object->pn_string);
cur_obj = object->pn_string;
data_type = att_list;
}
}
if (object->pn_type == MMS_PN_ATTR) {
/* Write the name/value for this obj.att */
if (print)
mms_trace(MMS_DEVP,
"set attr for obj.attr, %s",
object->pn_string);
cur_attr = object->pn_string;
data_type = obj_att;
}
if (data_type == obj_att) {
data_type = 0;
/* This is an obj_att */
(void) mm_add_int(0, format);
if (print)
mms_trace(MMS_DEVP,
"add 0 to int list %s.\"%s\"",
cur_obj, cur_attr);
}
if (data_type == att_list) {
data_type = 0;
/* This is an attr list */
/* Determine the number of attributes */
if (print)
mms_trace(MMS_DEVP,
"set attr num for %s",
cur_obj);
if (mm_db_exec(HERE, db,
"select * from \"%s\" limit 1;",
cur_obj) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"db error getting attribute number");
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
return (1);
}
num_atts = PQnfields(db->mm_db_results);
if (print)
mms_trace(MMS_DEVP,
"attr num is %d for %s",
num_atts,
cur_obj);
(void) mm_add_int(num_atts, format);
mm_clear_db(&db->mm_db_results);
}
}
/* done */
return (0);
}
int
mm_check_cmd_size(int header_length, char *text_clause, char *text_buf) {
int buf_len;
int clause_len;
int char_size = sizeof (char);
if (text_clause == NULL) {
/* is the 1st text clause, this must fit */
return (0);
}
if (text_buf == NULL) {
return (0);
}
buf_len = strlen(text_buf);
clause_len = strlen(text_clause);
if ((char_size * (header_length + buf_len + clause_len)) >
MM_CMD_SIZE_LIMIT) {
mms_trace(MMS_DEVP,
"header len == %d, buf len == %d, "
"clause len == %d, total == %d, "
"LIMIT == %d",
header_length, buf_len, clause_len,
header_length + buf_len + clause_len,
MM_CMD_SIZE_LIMIT);
return (1);
} else {
return (0);
}
}
static int
mm_sql_report(mm_command_t *cmd)
{
mm_db_t *db = &cmd->wka_ptr->mm_data->mm_db;
mms_par_node_t *report;
mms_par_node_t *reportmode;
PGresult *results;
int report_type = 2;
int name_rt = 1;
int namevalue_rt = 3;
/* buf for whole response */
char *resp_buf = NULL;
/* buf for multiple text clauses */
char *text_buf = NULL;
/* buf for a single text clause */
char *text_clause = NULL;
int number_of_rows = 0;
int row;
/* Report format */
mms_list_t format;
/* CMD size limit */
int header_length;
mms_trace(MMS_DEVP, "sql report");
mms_list_create(&format, sizeof (mm_char_list_t),
offsetof(mm_char_list_t, mm_char_list_next));
if (mm_db_exec(HERE, db, "%s;", cmd->cmd_buf) != MM_DB_DATA) {
mm_sql_db_err_rsp_new(cmd, db);
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
return (1);
}
if (PQresultStatus(db->mm_db_results) != PGRES_TUPLES_OK) {
SQL_CHK_LEN(&cmd->cmd_buf, 0, &cmd->cmd_bufsize,
strlen(ECLASS_INTERNAL) + strlen(EDATABASE) + 1);
(void) snprintf(cmd->cmd_buf, cmd->cmd_bufsize,
RESPONSE_ERROR, cmd->cmd_task,
ECLASS_INTERNAL, EDATABASE);
return (1);
}
number_of_rows = PQntuples(db->mm_db_results);
mms_trace(MMS_DEVP, "number of rows is %d", number_of_rows);
/* Only return info user wants. The default is value only. */
reportmode = mms_pn_lookup(cmd->cmd_root, "reportmode",
MMS_PN_CLAUSE, NULL);
if (reportmode && mms_pn_lookup(reportmode, "name",
MMS_PN_KEYWORD, NULL)) {
report_type = name_rt;
} else if (reportmode && mms_pn_lookup(reportmode, "namevalue",
MMS_PN_KEYWORD, NULL)) {
report_type = namevalue_rt;
} else if (reportmode && mms_pn_lookup(reportmode, "number",
MMS_PN_KEYWORD, NULL)) {
/* Generate a the number report and return */
text_buf = mms_strapp(text_buf,
"text[\"%d\"]",
number_of_rows);
if (cmd->cmd_buf != NULL) {
free(cmd->cmd_buf);
cmd->cmd_buf = NULL;
}
cmd->cmd_buf = mms_strapp(cmd->cmd_buf,
RESPONSE_SUCCESS_STR,
cmd->cmd_task,
text_buf);
free(text_buf);
mm_clear_db(&db->mm_db_results);
mms_trace(MMS_DEVP, "\n\n%s\n", cmd->cmd_buf);
return (0);
}
/* Build the text report */
/* there will be a text clause for each of the rows */
results = db->mm_db_results;
report = mms_pn_lookup(cmd->cmd_root, "report",
MMS_PN_CLAUSE, NULL);
if (report == NULL) {
/* no report clause */
/* there will be no text clause in response */
number_of_rows = 0;
} else {
/* Determine the formatting for the entire report */
if (mm_sql_format_report(cmd, report, &format)) {
mms_trace(MMS_ERR,
"error determineing report format");
mm_system_error(cmd,
"error determineing report format");
mm_clear_db(&results);
return (1);
}
}
if (number_of_rows != 0) {
/* There will be text clauses */
header_length = strlen(RESPONSE_INTERMEDIATE) +
strlen(cmd->cmd_task);
mms_trace(MMS_DEVP,
"response header size is %d",
header_length);
}
for (row = 0; row < number_of_rows; row++) {
text_clause = NULL;
if ((text_clause = mm_sql_report_text_row(cmd, row, results,
report_type,
&format)) == NULL) {
mms_trace(MMS_ERR,
"error generating text clause");
mm_system_error(cmd,
"error generating text clause");
mm_clear_db(&results);
return (1);
}
/* Check the MM_CMD_SIZE_LIMIT */
/* before appending the next text clause */
/* this command may need intermediate packets */
if (mm_check_cmd_size(header_length, text_clause, text_buf)) {
mm_char_list_t *node;
/* This text clause will push response over limit */
mms_trace(MMS_DEVP,
"command size over the limit");
/* add the curr text buf to the response list */
if (resp_buf)
free(resp_buf);
resp_buf = NULL;
resp_buf = mms_strapp(resp_buf, RESPONSE_INTERMEDIATE,
cmd->cmd_task,
text_buf);
node =
(mm_char_list_t *)malloc(sizeof (mm_char_list_t));
if (node == NULL) {
mms_trace(MMS_ERR,
"Error malloc response object");
mm_clear_db(&results);
return (1);
} else {
memset(node, 0, sizeof (mm_char_list_t));
node->text = NULL;
node->text = resp_buf;
mms_list_insert_tail(&cmd->cmd_resp_list, node);
resp_buf = NULL;
}
if (text_buf)
free(text_buf);
text_buf = NULL;
}
text_buf = mms_strapp(text_buf,
text_clause);
if (text_clause)
free(text_clause);
text_clause = NULL;
}
/* clean up formatting */
mm_free_list(&format);
mms_list_destroy(&format);
if (number_of_rows == 0) {
mm_char_list_t *node;
/* add the curr text buf to the response list */
if (resp_buf)
free(resp_buf);
resp_buf = NULL;
resp_buf = mms_strapp(resp_buf, RESPONSE_SUCCESS,
cmd->cmd_task);
node =
(mm_char_list_t *)malloc(sizeof (mm_char_list_t));
if (node == NULL) {
mms_trace(MMS_ERR, "Error malloc response object");
mm_clear_db(&results);
return (1);
} else {
memset(node, 0, sizeof (mm_char_list_t));
node->text = NULL;
node->text = resp_buf;
mms_list_insert_tail(&cmd->cmd_resp_list, node);
resp_buf = NULL;
}
/* Set the success response with no text */
SQL_CHK_LEN(&cmd->cmd_buf, 0, &cmd->cmd_bufsize,
strlen(RESPONSE_SUCCESS) +
strlen(cmd->cmd_task) + 1);
(void) snprintf(cmd->cmd_buf, cmd->cmd_bufsize,
RESPONSE_SUCCESS, cmd->cmd_task);
} else {
mm_char_list_t *node;
/* add the curr text buf to the response list */
if (resp_buf)
free(resp_buf);
resp_buf = NULL;
resp_buf = mms_strapp(resp_buf, RESPONSE_SUCCESS_STR,
cmd->cmd_task,
text_buf);
node = (mm_char_list_t *)malloc(sizeof (mm_char_list_t));
if (node == NULL) {
mms_trace(MMS_ERR, "Error malloc response object");
mm_clear_db(&results);
return (1);
} else {
memset(node, 0, sizeof (mm_char_list_t));
node->text = NULL;
node->text = resp_buf;
mms_list_insert_tail(&cmd->cmd_resp_list, node);
resp_buf = NULL;
}
/* Set the success response with a text */
SQL_CHK_LEN(&cmd->cmd_buf, 0, &cmd->cmd_bufsize,
strlen(RESPONSE_SUCCESS_STR) + strlen(cmd->cmd_task) +
strlen(text_buf) + 1);
(void) snprintf(cmd->cmd_buf, cmd->cmd_bufsize,
RESPONSE_SUCCESS_STR, cmd->cmd_task, text_buf);
}
if (text_buf)
free(text_buf);
mm_clear_db(&results);
return (0);
no_mem:
MM_ABORT_NO_MEM();
return (1);
}
static void
mm_sql_trans_volname(mm_command_t *cmd, int *offset)
{
mms_par_node_t *volname;
mms_par_node_t *arg;
int off = *offset;
mms_trace(MMS_DEVP, "sql trans volname");
MMS_PN_LOOKUP(volname, cmd->cmd_root, "volname",
MMS_PN_CLAUSE, NULL);
SQL_CHK_LEN(&cmd->cmd_buf, off, &cmd->cmd_bufsize, 1);
off += snprintf(cmd->cmd_buf + off, cmd->cmd_bufsize - off, "(");
mms_list_foreach(&volname->pn_arglist, arg) {
SQL_CHK_LEN(&cmd->cmd_buf, off, &cmd->cmd_bufsize,
28 + strlen(arg->pn_string));
off += snprintf(cmd->cmd_buf + off, cmd->cmd_bufsize - off,
"(\"VOLUME\".\"VolumeName\" = '%s')",
arg->pn_string);
if (arg != mms_list_tail(&volname->pn_arglist)) {
SQL_CHK_LEN(&cmd->cmd_buf, off,
&cmd->cmd_bufsize, 4);
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off, " OR ");
}
}
SQL_CHK_LEN(&cmd->cmd_buf, off, &cmd->cmd_bufsize, 1);
off += snprintf(cmd->cmd_buf + off, cmd->cmd_bufsize - off, ")");
*offset = off;
return;
no_mem:
MM_ABORT_NO_MEM();
return;
not_found:
mm_response_error(cmd,
ECLASS_LANGUAGE,
ENOTFOUND,
5062,
MESS_END);
return;
}
int
mm_make_constraint_helper(mms_par_node_t *node, mm_command_t *cmd,
int num, char **buf, int *offset,
int *bufsize, int current, int reg_ex) {
mms_par_node_t *arg;
mms_par_node_t *next_arg;
int off = *offset;
int b_size = *bufsize;
char *sql_ops;
const char *att_test;
char *att_cond;
char *obj;
char *att;
int cur = current;
int regex = reg_ex;
int twice = 0;
mms_trace(MMS_DEVP, "constraint helper -> num -> %d " \
" current -> %d", num, current);
if (node->pn_string != NULL) {
mms_trace(MMS_DEVP, "1 Object is %s", node->pn_string);
if (strcmp(node->pn_string, "regex") == 0) {
regex = 1;
}
}
if (*buf != NULL) {
mms_trace(MMS_DEVP, "1)%s", *buf);
}
if (node->pn_type & MMS_PN_STRING) {
if (cur == num) {
/* Could be numeric or null string or string. */
if (node->pn_type == MMS_PN_NUMERIC) {
SQL_CHK_LEN(buf, off, &b_size,
1 + strlen(node->pn_string));
off += snprintf(*buf + off, b_size - off,
"%s", node->pn_string);
} else if (node->pn_type & MMS_PN_NULLSTR) {
if (strcmp(*buf + off - 3, " = ") == 0) {
off -= 2; /* backup over operator */
SQL_CHK_LEN(buf, off, &b_size, 7);
off += snprintf(*buf + off, b_size - off, "ISNULL");
} else if (strcmp(*buf + off - 4, " <= ") == 0 ||
strcmp(*buf + off - 4, " >= ") == 0) {
off -= 3; /* backup over operator */
SQL_CHK_LEN(buf, off, &b_size, 7);
off += snprintf(*buf + off, b_size - off, "ISNULL");
} else if (strcmp(*buf + off - 4, " <> ") == 0) {
off -= 3; /* backup over operator */
SQL_CHK_LEN(buf, off, &b_size, 8);
off += snprintf(*buf + off, b_size - off, "NOTNULL");
} else {
SQL_CHK_LEN(buf, off, &b_size,
1 + strlen(node->pn_string));
off += snprintf(*buf + off, b_size - off,
"%s", node->pn_string);
}
} else {
SQL_CHK_LEN(buf, off, &b_size,
3 + strlen(node->pn_string));
off += snprintf(*buf + off, b_size - off,
"'%s'", node->pn_string);
}
}
if (!regex)
cur ++;
/* Just Worte a constraint value */
}
if (node->pn_type == MMS_PN_OBJ) {
/* An object-attribute */
twice = 0;
if (cur == num) {
if (*buf != NULL) {
twice = 1;
}
SQL_CHK_LEN(buf, off, &b_size,
4 + strlen(node->pn_string));
off += snprintf(*buf + off, b_size - off,
"\"%s\".", node->pn_string);
}
arg = mms_list_head(&node->pn_arglist);
if (cur == num) {
SQL_CHK_LEN(buf, off, &b_size,
3 + strlen(arg->pn_string));
off += snprintf(*buf + off, b_size - off,
"\"%s\"", arg->pn_string);
if (regex)
cur ++;
if (twice)
cur ++;
}
} else if (node->pn_flags & MMS_PN_MULTIOPS) {
/*
* A multiops has two or more args hanging off the arglist.
* Insert the ops between the args by adding an arg, then add
* the ops and repeat until the last arg.
*/
if (node->pn_flags & MMS_PN_REGEX) {
/* sql regular expression is at end of list */
arg = mms_list_head(&node->pn_arglist);
mms_list_remove(&node->pn_arglist, arg);
mms_list_insert_tail(&node->pn_arglist, arg);
}
mms_list_foreach(&node->pn_arglist, arg) {
cur = mm_make_constraint_helper(arg, cmd,
num, buf, &off,
&b_size, cur, regex);
if (arg != mms_list_tail(&node->pn_arglist)) {
sql_ops = mm_sql_get_ops(node->pn_string);
if ((strcmp(sql_ops, "AND") == 0) ||
(strcmp(sql_ops, "OR") == 0) ||
(strcmp(sql_ops, "NOT") == 0) ||
(strcmp(sql_ops, "ASC") == 0) ||
/* LINTED: dont change */
(strcmp(sql_ops, "DESC") == 0)) {
} else {
if (cur == num) {
SQL_CHK_LEN(buf, off,
&b_size,
3 + strlen(sql_ops));
off += snprintf(*buf + off, b_size - off,
" %s ", sql_ops);
}
}
}
}
if (node->pn_flags & MMS_PN_REGEX) {
/* restore list to original order */
arg = mms_list_tail(&node->pn_arglist);
mms_list_remove(&node->pn_arglist, arg);
mms_list_insert_head(&node->pn_arglist, arg);
}
} else if (node->pn_flags & MMS_PN_UNARYOPS) {
/* Unary ops has only one arg */
if (strcmp(node->pn_string, "isattr") == 0 ||
strcmp(node->pn_string, "noattr") == 0) {
att_test = "mm_obj_has_att('%s','%s') = '%s'";
if (strcmp(node->pn_string, "isattr") == 0) {
att_cond = "true";
} else {
att_cond = "false";
}
arg = mms_list_head(&node->pn_arglist);
obj = arg->pn_string;
next_arg = mms_list_head(&arg->pn_arglist);
att = next_arg->pn_string;
if (cur == num) {
SQL_CHK_LEN(buf, off, &b_size,
strlen(att_test) + 1);
off += snprintf(*buf + off, b_size - off,
att_test, obj, att, att_cond);
}
} else {
sql_ops = mm_sql_get_ops(node->pn_string);
if (cur == num) {
SQL_CHK_LEN(buf, off, &b_size,
strlen(sql_ops) + 3);
off += snprintf(*buf + off, b_size - off,
" %s ", sql_ops);
}
arg = mms_list_head(&node->pn_arglist);
cur = mm_make_constraint_helper(arg, cmd,
num, buf, &off,
&b_size, cur, regex);
}
}
*offset = off;
*bufsize = b_size;
return (cur);
no_mem:
MM_ABORT_NO_MEM();
return (MM_CMD_ERROR);
not_found:
return (MM_CMD_ERROR);
}
char *
mm_make_constraint(mm_command_t *cmd, int num) {
char *object;
char *buf = NULL;
mms_par_node_t *match;
mms_par_node_t *node;
int off = 0;
int bufsize = 0;
int cur = 0;
mms_trace(MMS_DEBUG, "mm_make_constraint");
object = (char *)mm_return_char(&cmd->cmd_dest_list, num);
match = mms_pn_lookup(cmd->cmd_root, "match",
MMS_PN_CLAUSE, NULL);
if (match == NULL) {
return (NULL);
}
mms_list_foreach(&match->pn_arglist, node) {
mms_trace(MMS_DEVP, "examing a node...");
off = 0;
bufsize = 0;
cur = mm_make_constraint_helper(node, cmd, num, &buf, &off,
&bufsize, cur, 0);
mms_trace(MMS_DEVP, "After helper...");
}
if (buf != NULL) {
mms_trace(MMS_DEVP, "Final Constraint for %s -> %s",
object, buf);
} else {
mms_trace(MMS_DEVP, "Final for %s is NULL",
object);
return (NULL);
}
return (buf);
}
int
mm_use_and_or(mm_command_t *cmd) {
/*
* return 1 if the operator is 'and'
* between constraints with indexes 'idx1' and 'idx2'
* return 0 if the operator is 'or'
*/
mms_par_node_t *match;
mms_par_node_t *node;
int oper = 1;
match = mms_pn_lookup(cmd->cmd_root, "match",
MMS_PN_CLAUSE, NULL);
if (match == NULL) {
return (NULL);
}
mms_list_foreach(&match->pn_arglist, node) {
mms_trace(MMS_DEVP, "examing a node...");
if (node->pn_string != NULL) {
mms_trace(MMS_DEVP, " Node is %s", node->pn_string);
if (strcmp(node->pn_string, "and") == 0) {
oper = 1;
}
if (strcmp(node->pn_string, "or") == 0) {
oper = 0;
}
}
}
return (oper);
}
int
mm_sql_report_func(mm_command_t *cmd, mm_db_t *db) {
char *buf = NULL;
mm_path_t *path = NULL;
char *joined[100];
int joined_count = 0;
int skip = 0;
int wrote_one = 0;
char *source_buf;
char *dest_buf;
char *savepoint = NULL;
int print_message = 0;
int i;
int y;
int j;
int k;
int x;
int l;
mms_trace(MMS_DEBUG, "mm_sql_make_sql_func");
for (y = 0; y < 100; y ++) {
joined[y] = NULL;
}
/* create report functins for each report onject */
for (i = 0; i < cmd->cmd_source_num; i ++) { /* source */
joined_count = 0;
/* Make report_n() for this source */
source_buf =
(char *)mm_return_char(&cmd->cmd_source_list, i);
buf = mms_strapp(buf,
"CREATE OR REPLACE FUNCTION "\
"report_%d_%d() RETURNS SETOF \"%s\" AS $$\n",
i, db->mm_db_fd, source_buf);
buf = mms_strapp(buf,
"select distinct \"%s\".* from \"%s\" ",
source_buf,
source_buf);
joined_count = 0;
joined[0] = NULL;
joined[0] = mms_strapp(joined[0], source_buf);
joined_count ++;
for (j = 0; j < cmd->cmd_dest_num; j ++) {
dest_buf =
(char *)mm_return_char(&cmd->cmd_dest_list, j);
if (print_message) {
mms_trace(MMS_DEVP, " 1) Dest %d -> %s",
j, dest_buf);
mms_trace(MMS_DEVP, "mm_get_path(%s, %s)",
dest_buf,
source_buf);
}
if ((path = mm_get_path(dest_buf,
source_buf)) == NULL) {
mms_trace(MMS_DEVP, "Path is NULL, %s to %s",
dest_buf,
source_buf);
} else {
for (k = 0; k < path->mm_node_num; k++) {
skip = 0;
for (x = 0; x < joined_count; x++) {
if (strcmp(joined[x],
path->mm_node[k]->mm_obj) == 0) {
/* same so skip */
skip = 1;
}
}
if (!skip) {
buf = mms_strapp(buf,
"\ncross join \"%s\" ",
path->mm_node[k]->mm_obj);
joined[joined_count] = NULL;
joined[joined_count] =
mms_strapp(joined[joined_count],
path->mm_node[k]->mm_obj);
joined_count ++;
}
}
}
}
if (cmd->cmd_dest_num == 0) {
buf = mms_strapp(buf,
";\n");
}
for (j = 0; j < cmd->cmd_dest_num; j ++) {
/* j cmd_dest_num */
if (j == 0) {
buf = mms_strapp(buf,
"\nwhere \n(\n");
}
dest_buf =
(char *)mm_return_char(&cmd->cmd_dest_list, j);
if (print_message) {
mms_trace(MMS_DEVP, " 2) Dest %d -> %s",
j, dest_buf);
mms_trace(MMS_DEVP, "mm_get_path(%s, %s)",
dest_buf,
source_buf);
}
if ((path = mm_get_path(dest_buf,
source_buf)) == NULL) {
if (strcmp(dest_buf,
source_buf) == 0) {
/* same object */
buf = mms_strapp(buf, "(true)\n");
wrote_one = 1;
} else {
/* no path between */
buf = mms_strapp(buf, "(false)\n");
wrote_one = 1;
}
} else {
for (k = path->mm_node_num - 1; k >= 0; k--) {
/* node[%d] has %d edges, k, */
/* path->mm_node[k]->mm_edge_num */
for (l = 0;
l < path->mm_node[k]->mm_edge_num;
l++) {
/*
* if (path->mm_node[k]->
* mm_edge[l]->mm_ref_att != NULL) {
*
* }
*/
/* add this edge constraint */
wrote_one = 1;
if (k == path->mm_node_num - 1) {
buf = mms_strapp(buf,
"(\"%s\".",
source_buf);
} else {
buf = mms_strapp(buf,
"(\"%s\".",
path->mm_node
[k+1]->mm_obj);
}
if (path->mm_node[k]->
mm_edge[l]->mm_ref_att == NULL) {
buf = mms_strapp(buf,
"\"%s\" = ",
path->mm_node[k]->
mm_edge[l]->mm_att);
} else {
buf = mms_strapp(buf,
"\"%s\" = ",
path->mm_node[k]->
mm_edge[l]->mm_ref_att);
}
buf = mms_strapp(buf,
"\"%s\".\"%s\")\n",
path->mm_node[k]->mm_obj,
path->mm_node[k]->
mm_edge[l]->mm_att);
if (l+1 < path->mm_node[k]->
mm_edge_num) {
buf = mms_strapp(buf, "and\n");
}
}
if (k - 1 >= 0) {
buf = mms_strapp(buf, "and\n");
}
}
}
if (j + 1 < cmd->cmd_dest_num) {
buf = mms_strapp(buf, "and\n");
}
if (j + 1 == cmd->cmd_dest_num) {
int p;
/* Add all constraints here */
for (p = 0;
p < cmd->cmd_const_num;
p ++) {
if (p == 0) {
if (wrote_one)
buf = mms_strapp(buf,
"and\n(\n");
}
buf = mms_strapp(buf,
(char *)
mm_return_char(&cmd->
cmd_const_list, p));
if (p+1 < cmd->cmd_const_num) {
buf =
mms_strapp(buf,
"and\n");
}
if (p + 1 ==
cmd->cmd_const_num) {
/* parenn for constraints */
buf = mms_strapp(buf, ")\n");
}
}
/* paren for where ( */
if (wrote_one) {
buf = mms_strapp(buf,
");\n");
} else {
buf = mms_strapp(buf,
";\n");
}
}
}
buf = mms_strapp(buf,
"$$ LANGUAGE SQL;\n");
savepoint = mms_strnew("report_%d_%d", i, db->mm_db_fd);
if (mm_db_txn_savepoint(db, savepoint) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_sql_report_func: "
"db error setting savepoint");
}
if (mm_db_exec(HERE, db, "drop function report_%d_%d();", i,
db->mm_db_fd) !=
MM_DB_OK) {
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
if (mm_db_txn_savepoint_rollback(db,
savepoint) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_sql_report_func: "
"db error rollingback savepoint");
}
}
if (mm_db_txn_release_savepoint(db,
savepoint) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_sql_report_func: "
"db error releaseing savepoint");
}
free(savepoint);
if (mm_db_exec(HERE, db, buf) != MM_DB_OK) {
mms_trace(MMS_ERR, "Error adding path match function");
mm_sql_db_err_rsp_new(cmd, db);
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
free(buf);
return (1);
}
free(buf);
buf = NULL;
for (y = 0; y < joined_count; y ++) {
free(joined[y]);
joined[y] = NULL;
}
}
return (0);
}
int
mm_sql_report_func_attr(mm_command_t *cmd) {
char *buf = NULL;
char *order_buf = NULL;
mm_path_t *path = NULL;
char *joined[100];
int joined_count = 0;
int skip = 0;
mm_db_t *db = &cmd->cmd_mm_data->mm_db;
int wrote_one = 0;
char *temp_buf = NULL;
char *savepoint = NULL;
char *source_buf;
char *dest_buf;
int y;
int j;
int k;
int x;
int l;
int p;
int i;
mms_trace(MMS_DEBUG, "mm_sql_make_sql_func_attr");
for (y = 0; y < 100; y ++) {
joined[y] = NULL;
}
/* create report functins for each report onject */
for (i = 0; i < cmd->cmd_source_num; i ++) { /* source */
joined_count = 0;
/* Make report_n() for this source */
source_buf =
(char *)mm_return_char(&cmd->cmd_source_list, i);
buf = mms_strapp(buf,
"CREATE OR REPLACE FUNCTION "\
"report_%d_%d() RETURNS SETOF \"%s\" AS $$\n",
i, db->mm_db_fd, source_buf);
buf = mms_strapp(buf,
"select distinct \"%s\".* from \"%s\" ",
source_buf,
source_buf);
joined_count = 0;
joined[0] = NULL;
joined[0] = mms_strapp(joined[0], source_buf);
joined_count ++;
for (j = 0; j < cmd->cmd_dest_num; j ++) {
dest_buf =
(char *)mm_return_char(&cmd->cmd_dest_list, j);
if ((path = mm_get_path(dest_buf,
source_buf)) == NULL) {
mms_trace(MMS_DEVP, "Path is NULL, %s to %s",
dest_buf,
source_buf);
} else {
for (k = 0; k < path->mm_node_num; k++) {
skip = 0;
for (x = 0; x < joined_count; x++) {
if (strcmp(joined[x],
path->mm_node[k]->mm_obj) == 0) {
/* same so skip */
skip = 1;
}
}
if (!skip) {
buf = mms_strapp(buf,
"\ncross join \"%s\" ",
path->mm_node[k]->mm_obj);
joined[joined_count] = NULL;
joined[joined_count] =
mms_strapp(joined[joined_count],
path->mm_node[k]->mm_obj);
joined_count ++;
}
}
}
}
order_buf = mm_sql_order_buf(cmd);
buf = mms_strapp(buf, order_buf);
if (order_buf != NULL)
free(order_buf);
for (j = 0; j < cmd->cmd_dest_num; j ++) {
dest_buf =
(char *)mm_return_char(&cmd->cmd_dest_list, j);
/* j cmd_dest_num */
if (j == 0) {
buf = mms_strapp(buf,
"\nwhere \n(\n");
}
if ((path = mm_get_path(dest_buf,
source_buf)) == NULL) {
if (strcmp(dest_buf,
source_buf) == 0) {
/* same object */
buf = mms_strapp(buf, "(true)\n");
wrote_one = 1;
} else {
/* no path between */
buf = mms_strapp(buf, "(false)\n");
wrote_one = 1;
}
} else {
for (k = path->mm_node_num - 1; k >= 0; k--) {
for (l = 0;
l < path->mm_node[k]->mm_edge_num;
l++) {
/*
* if (path->mm_node[k]->
* mm_edge[l]->mm_ref_att != NULL) {
*
* }
*/
/* add this edge constraint */
wrote_one = 1;
if (k == path->mm_node_num - 1) {
buf = mms_strapp(buf,
"(\"%s\".",
source_buf);
} else {
buf = mms_strapp(buf,
"(\"%s\".",
path->mm_node
[k+1]->mm_obj);
}
if (path->mm_node[k]->
mm_edge[l]->mm_ref_att == NULL) {
buf = mms_strapp(buf,
"\"%s\" = ",
path->mm_node[k]->
mm_edge[l]->mm_att);
} else {
buf = mms_strapp(buf,
"\"%s\" = ",
path->mm_node[k]->
mm_edge[l]->mm_ref_att);
}
buf = mms_strapp(buf,
"\"%s\".\"%s\")\n",
path->mm_node[k]->mm_obj,
path->mm_node[k]->
mm_edge[l]->mm_att);
if (l+1 < path->mm_node[k]->
mm_edge_num) {
buf = mms_strapp(buf, "and\n");
}
}
if (k - 1 >= 0) {
buf = mms_strapp(buf, "and\n");
}
}
}
if (j + 1 < cmd->cmd_dest_num) {
buf = mms_strapp(buf, "and\n");
}
if (j + 1 == cmd->cmd_dest_num) {
/* Add all constraints here */
for (p = 0;
p < cmd->cmd_const_num;
p ++) {
if (p == 0) {
if (wrote_one)
buf = mms_strapp(buf,
"and\n(\n");
}
buf = mms_strapp(buf,
(char *)
mm_return_char(&cmd->
cmd_const_list, p));
if (p+1 < cmd->cmd_const_num) {
buf =
mms_strapp(buf,
"and\n");
}
if (p + 1 ==
cmd->cmd_const_num) {
/* parenn for constraints */
buf = mms_strapp(buf, ")\n");
}
}
/* paren for where ( */
if (wrote_one) {
buf = mms_strapp(buf,
")\n");
} else {
buf = mms_strapp(buf,
"\n");
}
}
}
temp_buf = mms_strapp(temp_buf, mm_sql_number_buf(cmd));
if (temp_buf != NULL) {
buf = mms_strapp(buf, temp_buf);
free(temp_buf);
}
buf = mms_strapp(buf,
" ; $$ LANGUAGE SQL;\n");
savepoint = mms_strnew("report_%d_%d", i, db->mm_db_fd);
if (mm_db_txn_savepoint(db,
savepoint) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_sql_report_func_attr: "
"db error setting savepoint");
}
if (mm_db_exec(HERE, db, "drop function report_%d_%d();", i,
db->mm_db_fd) !=
MM_DB_OK) {
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
if (mm_db_txn_savepoint_rollback(db,
savepoint) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_sql_report_func_attr: "
"db error setting savepoint");
}
}
if (mm_db_txn_release_savepoint(db,
savepoint) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_sql_report_func_attr: "
"db error releaseing savepoint");
}
free(savepoint);
if (mm_db_exec(HERE, db, buf) != MM_DB_OK) {
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
mms_trace(MMS_ERR, "Error adding path match function");
return (1);
}
free(buf);
buf = NULL;
for (y = 0; y < joined_count; y ++) {
free(joined[y]);
joined[y] = NULL;
}
}
return (0);
}
int
mm_sql_from_where(mm_command_t *cmd, mm_db_t *db)
{
char *buf = NULL;
char *final_buf = NULL;
mm_path_t *path = NULL;
char *joined[100];
int joined_count = 0;
int skip = 0;
mm_pkey_t *p_key = NULL;
char *source_buf_i;
char *source_buf_j;
int y;
int i;
int j;
int k;
int x;
int l;
mms_trace(MMS_DEVP, "mm_sql_from_where");
for (y = 0; y < 100; y ++) {
joined[y] = NULL;
}
/* Generate all report_n() for this command */
if (mm_sql_report_func(cmd, db)) {
mms_trace(MMS_ERR,
"error creating report funcs");
return (1);
}
joined_count = 0;
for (i = 0; i < cmd->cmd_source_num; i ++) {
/*
* ex, i = 0
* report_0() t0, "DM"
* t0 is arbitrary table alias
*/
source_buf_i = (char *)mm_return_char(&cmd->cmd_source_list, i);
buf = mms_strapp(buf,
"\nreport_%d_%d() t%d, \"%s\" ",
i, db->mm_db_fd, i, source_buf_i);
joined[i] = NULL;
joined[i] = mms_strapp(joined[i],
source_buf_i);
joined_count ++;
if (i+1 < cmd->cmd_source_num) {
buf = mms_strapp(buf,
"cross join ");
}
}
/* Add objects to FROM clause */
/* add implied constraints between source objects */
for (i = 0; i < cmd->cmd_source_num; i ++) {
source_buf_i = (char *)mm_return_char(&cmd->cmd_source_list, i);
for (j = i+1; j < cmd->cmd_source_num; j ++) {
source_buf_j = (char *)
mm_return_char(&cmd->cmd_source_list, j);
if ((path = mm_get_path(source_buf_j,
source_buf_i)) != NULL) {
for (k = 0; k < path->mm_node_num; k++) {
skip = 0;
for (x = 0; x < joined_count; x++) {
if (strcmp(joined[x],
path->mm_node[k]->
mm_obj) == 0) {
/* same so skip */
skip = 1;
}
}
if (!skip) {
buf = mms_strapp(buf,
"\ncross join \n\"%s\" ",
path->mm_node[k]->mm_obj);
joined[joined_count] = NULL;
joined[joined_count] =
mms_strapp(joined[joined_count],
path->mm_node[k]->mm_obj);
joined_count ++;
}
}
}
}
}
buf = mms_strapp(buf, "\nwhere \n(\n");
for (i = 0; i < cmd->cmd_source_num; i ++) {
source_buf_i = (char *)mm_return_char(&cmd->cmd_source_list, i);
p_key = mm_get_pkey(source_buf_i);
for (j = 0; j < p_key->mm_att_num; j ++) {
buf = mms_strapp(buf,
"(t%d.\"%s\" = \"%s\".\"%s\")\n",
i, p_key->mm_att[j], source_buf_i,
p_key->mm_att[j]);
if (j+1 < p_key->mm_att_num) {
buf = mms_strapp(buf, "and\n");
}
}
if (i+1 < cmd->cmd_source_num) {
buf = mms_strapp(buf, "and\n");
}
}
/* Now add the implied path constraints */
for (i = 0; i < cmd->cmd_source_num; i ++) {
source_buf_i = (char *)mm_return_char(&cmd->cmd_source_list, i);
for (j = i+1; j < cmd->cmd_source_num; j ++) {
source_buf_j = (char *)
mm_return_char(&cmd->cmd_source_list, j);
if ((path = mm_get_path(source_buf_j,
source_buf_i)) != NULL) {
for (k = path->mm_node_num - 1; k >= 0; k--) {
for (l = 0;
l < path->mm_node[k]->mm_edge_num;
l++) {
/*
* if (path->mm_node[k]->
* mm_edge[l]->mm_ref_att != NULL) {
*
* }
*/
/* add this edge constraint */
/* will always need an 'and' */
buf = mms_strapp(buf, "and\n");
if (k == path->mm_node_num - 1) {
buf = mms_strapp(buf,
"(\"%s\".",
source_buf_i);
} else {
buf = mms_strapp(buf,
"(\"%s\".",
path->mm_node
[k+1]->mm_obj);
}
if (path->mm_node[k]->
mm_edge[l]->mm_ref_att == NULL) {
buf = mms_strapp(buf,
"\"%s\" = ",
path->mm_node[k]->
mm_edge[l]->mm_att);
} else {
buf = mms_strapp(buf,
"\"%s\" = ",
path->mm_node[k]->
mm_edge[l]->mm_ref_att);
}
buf = mms_strapp(buf,
"\"%s\".\"%s\")\n",
path->mm_node[k]->mm_obj,
path->mm_node[k]->
mm_edge[l]->mm_att);
}
}
}
}
}
buf = mms_strapp(buf, ")\n");
final_buf = mms_strapp(final_buf, cmd->cmd_buf);
final_buf = mms_strapp(final_buf, buf);
SQL_CHK_LEN(&cmd->cmd_buf, NULL,
&cmd->cmd_bufsize, strlen(final_buf) + 1);
strcpy(cmd->cmd_buf, final_buf);
for (y = 0; y < joined_count; y ++) {
free(joined[y]);
joined[y] = NULL;
}
free(buf);
free(final_buf);
return (0);
no_mem:
MM_ABORT_NO_MEM();
return (1);
}
int
mm_attribute_match(mm_command_t *cmd) {
char *buf = NULL;
mm_db_t *db = &cmd->cmd_mm_data->mm_db;
mm_pkey_t *p_key = NULL;
int j;
int i;
char *source_buf_0;
mms_trace(MMS_DEBUG, "mm_attribute_match");
buf = mms_strapp(buf, cmd->cmd_buf);
mms_trace(MMS_DEVP, "buf is %s",
buf);
buf = mms_strapp(buf, "\nwhere\n");
/* get pkey for this source */
source_buf_0 = (char *)mm_return_char(&cmd->cmd_source_list, 0);
p_key = mm_get_pkey(source_buf_0);
buf = mms_strapp(buf, "(\n");
for (j = 0; j < p_key->mm_att_num; j ++) {
buf = mms_strapp(buf,
"(\"%s\".\"%s\" in \n",
source_buf_0,
p_key->mm_att[j]);
buf = mms_strapp(buf,
"(select \"%s\".\"%s\" from "\
"report_0_%d() t%d, \"%s\" where\n",
source_buf_0,
p_key->mm_att[j],
db->mm_db_fd,
j,
source_buf_0);
buf = mms_strapp(buf, "(\n");
for (i = 0; i < p_key->mm_att_num; i ++) {
buf = mms_strapp(buf,
"(t%d.\"%s\" = \"%s\".\"%s\") ",
j,
p_key->mm_att[i],
source_buf_0,
p_key->mm_att[i]);
if (i+1 < p_key->mm_att_num) {
buf = mms_strapp(buf, "and\n");
}
}
buf = mms_strapp(buf, ")\n");
buf = mms_strapp(buf, ")\n");
buf = mms_strapp(buf, ")\n");
if (j+1 < p_key->mm_att_num) {
buf = mms_strapp(buf, "and\n");
}
}
buf = mms_strapp(buf, ")\n");
SQL_CHK_LEN(&cmd->cmd_buf, NULL,
&cmd->cmd_bufsize, strlen(buf) + 1);
strcpy(cmd->cmd_buf, buf);
free(buf);
return (INTRP_OK);
no_mem:
MM_ABORT_NO_MEM();
return (MM_CMD_ERROR);
}
static int
mm_sql_trans_match_exp(mms_par_node_t *node, mm_command_t *cmd,
int *offset, int host_ident)
{
mms_par_node_t *arg;
mms_par_node_t *next_arg;
int off = *offset;
char *sql_ops;
const char *att_test;
char *att_cond;
char *obj;
char *att;
int need_int_cast = 0;
int need_host_ident = 0;
int print_message = 0;
mms_trace(MMS_DEVP, "sql trans match exp");
if (cmd->cmd_buf != NULL) {
if (print_message)
mms_trace(MMS_DEVP,
" cmdbuf == %s",
cmd->cmd_buf);
} else {
if (print_message)
mms_trace(MMS_DEVP,
" cmd_buf is NULL");
}
if (node->pn_type & MMS_PN_STRING) {
if (print_message)
mms_trace(MMS_DEVP,
" (node->pn_type & MMS_PN_STRING)");
/* Could be numeric or null string or string. */
if (node->pn_type == MMS_PN_NUMERIC) {
SQL_CHK_LEN(&cmd->cmd_buf, off, &cmd->cmd_bufsize,
1 + strlen(node->pn_string));
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off,
"%s", node->pn_string);
} else if (node->pn_type & MMS_PN_NULLSTR) {
/* Still support NULLSTR ?? */
if (strcmp(&cmd->cmd_buf[off - 3], " = ") == 0) {
off -= 2; /* backup over operator */
SQL_CHK_LEN(&cmd->cmd_buf,
off, &cmd->cmd_bufsize, 7);
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off, "ISNULL");
} else if (strcmp(&cmd->cmd_buf[off - 4],
" <= ") == 0 ||
strcmp(&cmd->cmd_buf[off - 4],
" >= ") == 0) {
off -= 3; /* backup over operator */
SQL_CHK_LEN(&cmd->cmd_buf, off,
&cmd->cmd_bufsize, 7);
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off, "ISNULL");
} else if (strcmp(&cmd->cmd_buf[off - 4],
" <> ") == 0) {
off -= 3; /* backup over operator */
SQL_CHK_LEN(&cmd->cmd_buf, off,
&cmd->cmd_bufsize, 8);
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off, "NOTNULL");
} else {
SQL_CHK_LEN(&cmd->cmd_buf,
off, &cmd->cmd_bufsize,
1 + strlen(node->pn_string));
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off,
"%s", node->pn_string);
}
} else {
if (host_ident) {
SQL_CHK_LEN(&cmd->cmd_buf, off,
&cmd->cmd_bufsize, 15);
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off,
"pg_host_ident(");
}
SQL_CHK_LEN(&cmd->cmd_buf, off, &cmd->cmd_bufsize,
3 + strlen(node->pn_string));
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off,
"'%s'", node->pn_string);
if (host_ident) {
SQL_CHK_LEN(&cmd->cmd_buf, off,
&cmd->cmd_bufsize, 2);
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off, ")");
}
}
}
if (node->pn_type == MMS_PN_OBJ) {
if (print_message)
mms_trace(MMS_DEVP,
" node->pn_type == MMS_PN_OBJ");
/* An object-attribute */
if (cmd->cmd_notify_to == 1) {
SQL_CHK_LEN(&cmd->cmd_buf, off, &cmd->cmd_bufsize,
2 + strlen("NEW"));
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off, "%s.", "NEW");
} else {
SQL_CHK_LEN(&cmd->cmd_buf, off, &cmd->cmd_bufsize,
4 + strlen(node->pn_string));
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off,
"\"%s\".", node->pn_string);
}
arg = mms_list_head(&node->pn_arglist);
SQL_CHK_LEN(&cmd->cmd_buf, off, &cmd->cmd_bufsize,
3 + strlen(arg->pn_string));
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off,
"\"%s\"", arg->pn_string);
} else if (node->pn_flags & MMS_PN_MULTIOPS) {
if (print_message)
mms_trace(MMS_DEVP,
"(node->pn_flags & MMS_PN_MULTIOPS)");
if (node->pn_string != NULL) {
if ((strcmp(node->pn_string,
"numeq") == 0) ||
(strcmp(node->pn_string,
"numne") == 0) ||
(strcmp(node->pn_string,
"numlt") == 0) ||
(strcmp(node->pn_string,
"numle") == 0) ||
(strcmp(node->pn_string,
"numgt") == 0) ||
(strcmp(node->pn_string,
"numge") == 0)) {
SQL_CHK_LEN(&cmd->cmd_buf, off,
&cmd->cmd_bufsize, 6);
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off, "int4(");
need_int_cast = 1;
}
if (print_message)
mms_trace(MMS_DEVP,
" %s",
node->pn_string);
if ((strcmp(node->pn_string,
"hosteq") == 0) ||
(strcmp(node->pn_string,
"hostne") == 0)) {
SQL_CHK_LEN(&cmd->cmd_buf, off,
&cmd->cmd_bufsize, 15);
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off,
"pg_host_ident(");
need_int_cast = 1;
need_host_ident = 1;
}
}
/*
* A multiops has two or more args hanging off the arglist.
* Insert the ops between the args by adding an arg, then add
* the ops and repeat until the last arg.
*/
if (node->pn_flags & MMS_PN_REGEX) {
/* sql regular expression is at end of list */
arg = mms_list_head(&node->pn_arglist);
mms_list_remove(&node->pn_arglist, arg);
mms_list_insert_tail(&node->pn_arglist, arg);
}
mms_list_foreach(&node->pn_arglist, arg) {
if (arg->pn_type == MMS_PN_OPS) {
SQL_CHK_LEN(&cmd->cmd_buf, off,
&cmd->cmd_bufsize, 2);
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off, "(");
}
if (mm_sql_trans_match_exp(arg, cmd,
&off, need_host_ident)) {
mms_trace(MMS_ERR,
"mm_sql_trans_match_exp: "
"error translating match expression");
return (1);
}
if (arg->pn_type == MMS_PN_OPS) {
SQL_CHK_LEN(&cmd->cmd_buf, off,
&cmd->cmd_bufsize, 2);
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off, ")");
}
if (need_int_cast) {
SQL_CHK_LEN(&cmd->cmd_buf, off,
&cmd->cmd_bufsize, 2);
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off, ")");
need_int_cast = 0;
}
if (arg != mms_list_tail(&node->pn_arglist)) {
sql_ops = mm_sql_get_ops(node->pn_string);
SQL_CHK_LEN(&cmd->cmd_buf, off,
&cmd->cmd_bufsize,
3 + strlen(sql_ops));
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off,
" %s ", sql_ops);
}
}
if (node->pn_flags & MMS_PN_REGEX) {
/* restore list to original order */
arg = mms_list_tail(&node->pn_arglist);
mms_list_remove(&node->pn_arglist, arg);
mms_list_insert_head(&node->pn_arglist, arg);
}
} else if (node->pn_flags & MMS_PN_UNARYOPS) {
if (print_message)
mms_trace(MMS_DEVP,
"(node->pn_flags & MMS_PN_UNARYOPS)");
/* Unary ops has only one arg */
if (strcmp(node->pn_string, "isset") == 0 ||
strcmp(node->pn_string, "notset") == 0) {
arg = mms_list_head(&node->pn_arglist);
if (mm_sql_trans_match_exp(arg, cmd,
&off, need_host_ident)) {
mms_trace(MMS_ERR,
"mm_sql_trans_match_exp: "
"error translating match expression");
return (1);
}
if (strcmp(node->pn_string, "isset") == 0) {
/* isset */
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off,
" IS NOT NULL");
} else {
/* notnot */
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off,
" ISNULL");
}
} else if (strcmp(node->pn_string, "isattr") == 0 ||
strcmp(node->pn_string, "noattr") == 0) {
att_test = "mm_obj_has_att('%s','%s') = '%s'";
if (strcmp(node->pn_string, "isattr") == 0) {
att_cond = "true";
} else {
att_cond = "false";
}
arg = mms_list_head(&node->pn_arglist);
obj = arg->pn_string;
next_arg = mms_list_head(&arg->pn_arglist);
att = next_arg->pn_string;
SQL_CHK_LEN(&cmd->cmd_buf, off, &cmd->cmd_bufsize,
strlen(att_test) + 1);
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off,
att_test, obj, att, att_cond);
} else {
sql_ops = mm_sql_get_ops(node->pn_string);
SQL_CHK_LEN(&cmd->cmd_buf, off, &cmd->cmd_bufsize,
strlen(sql_ops) + 3);
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off,
" %s ", sql_ops);
SQL_CHK_LEN(&cmd->cmd_buf, off, &cmd->cmd_bufsize, 2);
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off, "(");
arg = mms_list_head(&node->pn_arglist);
if (mm_sql_trans_match_exp(arg, cmd,
&off, need_host_ident)) {
mms_trace(MMS_ERR,
"mm_sql_trans_match_exp: "
"error translating match expression");
return (1);
}
SQL_CHK_LEN(&cmd->cmd_buf, off, &cmd->cmd_bufsize, 2);
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off, ")");
}
}
*offset = off;
return (0);
no_mem:
MM_ABORT_NO_MEM();
return (1);
not_found:
mm_response_error(cmd,
ECLASS_LANGUAGE,
ENOTFOUND,
5062,
MESS_END);
return (1);
}
void
mm_sql_number(mm_command_t *cmd)
{
char *buf = NULL;
char *final_buf = NULL;
char *number_buf = NULL;
mms_trace(MMS_DEVP, "mm_sql_number");
/* This function will append the number buf to cmd_buf */
number_buf = mm_sql_number_buf(cmd);
buf = mms_strapp(buf, number_buf);
if (number_buf != NULL)
free(number_buf);
if (buf == NULL) {
return;
}
final_buf = mms_strapp(final_buf, cmd->cmd_buf);
final_buf = mms_strapp(final_buf, buf);
SQL_CHK_LEN(&cmd->cmd_buf, NULL,
&cmd->cmd_bufsize, strlen(final_buf) + 1);
strcpy(cmd->cmd_buf, final_buf);
if (buf)
free(buf);
if (final_buf)
free(final_buf);
return;
no_mem:
MM_ABORT_NO_MEM();
}
char *
mm_sql_number_buf(mm_command_t *cmd)
{
/* This function returns a buf of the number clause */
mms_par_node_t *number;
mms_par_node_t *range;
mms_par_node_t *node;
mms_par_node_t *arg1;
mms_par_node_t *arg2;
int range1 = 0;
int range2 = 0;
int val;
char *buf = NULL;
mms_par_node_t *work;
mms_trace(MMS_DEVP, "mm_sql_number_buf");
number = mms_pn_lookup(cmd->cmd_root, "number",
MMS_PN_CLAUSE, NULL);
if (number == NULL) {
mms_trace(MMS_DEVP, "didn't find a number clause");
return (NULL);
}
/*
* Subtract one from the number because the postgres data index
* starts at zero and the mmp command number starts at one.
*/
node = mms_list_head(&number->pn_arglist);
if ((range = mms_pn_lookup(number, NULL,
MMS_PN_RANGE, NULL)) != NULL) {
mms_trace(MMS_DEVP, "inside range..");
work = NULL;
/* Have a range */
/* get the 1st and last arg */
arg1 = mms_pn_lookup(range, NULL,
MMS_PN_STRING, &work);
arg2 = mms_pn_lookup(range, NULL,
MMS_PN_STRING, &work);
if ((arg1->pn_string == NULL) ||
(arg2->pn_string == NULL)) {
mms_trace(MMS_ERR,
"an arg in range cannot be NULL");
return (buf);
}
if (strcmp(arg1->pn_string, "FIRST") == 0) {
if (arg2->pn_type & MMS_PN_NUMERIC) {
range1 = 1;
sscanf(arg2->pn_string, "%d", &range2);
} else {
return (buf);
}
} else if (strcmp(arg2->pn_string, "LAST") == 0) {
if (arg1->pn_type & MMS_PN_NUMERIC) {
sscanf(arg1->pn_string, "%d", &val);
val -= 1;
buf = mms_strapp(buf, " OFFSET %d ", val);
return (buf);
} else {
return (buf);
}
} else if (arg1->pn_type & MMS_PN_NUMERIC &&
arg2->pn_type & MMS_PN_NUMERIC) {
sscanf(arg1->pn_string, "%d", &range1);
sscanf(arg2->pn_string, "%d", &range2);
} else {
return (buf);
}
range1 -= 1;
range2 -= 1;
buf = mms_strapp(buf, " LIMIT %d OFFSET %d ",
range2 - range1 + 1, range1);
} else if (strcmp(node->pn_string, "FIRST") == 0) {
buf = mms_strapp(buf, " LIMIT 1 OFFSET 0 ");
} else if (node->pn_type & MMS_PN_NUMERIC) {
sscanf(node->pn_string, "%d", &val);
val -= 1;
buf = mms_strapp(buf, " LIMIT 1 OFFSET %d ", val);
}
if (buf == NULL) {
mms_trace(MMS_ERR,
"found a number clause, "
"but didn't write any sql");
mms_trace(MMS_DEVP, "Number buf is NULL");
return (buf);
}
return (buf);
no_mem:
MM_ABORT_NO_MEM();
return (NULL);
not_found:
return (NULL);
}
int
mm_get_range(mm_command_t *cmd, mm_range_t *range)
{
mms_par_node_t *number;
mms_par_node_t *node;
mms_par_node_t *arg1;
mms_par_node_t *arg2;
/*
* Get number clause range, number[a..b] or number[a]
*/
memset(range, 0, sizeof (mm_range_t));
if ((number = mms_pn_lookup(cmd->cmd_root, "number",
MMS_PN_CLAUSE, NULL)) == NULL) {
/* no number */
range->mm_range_type = MM_RANGE_NONE;
return (0);
}
node = mms_list_head(&number->pn_arglist);
if (node->pn_type == MMS_PN_RANGE) {
/* number range */
arg1 = mms_list_head(&node->pn_arglist);
arg2 = mms_list_tail(&node->pn_arglist);
if (strcmp(arg1->pn_string, "FIRST") == 0 &&
strcmp(arg2->pn_string, "LAST") == 0) {
mms_trace(MMS_DEVP, "number-clause range first-last");
range->mm_range_type = MM_RANGE_FIRST_LAST;
range->mm_range_first = 1;
return (0);
} else if (strcmp(arg1->pn_string, "FIRST") == 0) {
range->mm_range_type = MM_RANGE_FIRST;
range->mm_range_first = 1;
if (arg2->pn_type & MMS_PN_NUMERIC) {
range->mm_range_last =
atoi(arg2->pn_string);
mms_trace(MMS_DEVP,
"number-clause range first-%d",
range->mm_range_last);
return (0);
}
} else if (strcmp(arg2->pn_string, "LAST") == 0) {
range->mm_range_type = MM_RANGE_LAST;
if (arg1->pn_type & MMS_PN_NUMERIC) {
range->mm_range_first =
atoi(arg1->pn_string);
mms_trace(MMS_DEVP, "number-clause "
"range %d-last",
range->mm_range_first);
return (0);
}
} else if (arg1->pn_type & MMS_PN_NUMERIC &&
arg2->pn_type & MMS_PN_NUMERIC) {
range->mm_range_type = MM_RANGE_NUMS;
range->mm_range_first = atoi(arg1->pn_string);
range->mm_range_last = atoi(arg2->pn_string);
mms_trace(MMS_DEVP, "number-clause range %d-%d",
range->mm_range_first, range->mm_range_last);
return (0);
}
mms_trace(MMS_DEVP, "number-clause range lookup failed");
return (1);
}
/* single number */
range->mm_range_type = MM_RANGE_A_NUM;
range->mm_range_first = atoi(node->pn_string);
mms_trace(MMS_DEVP, "number-clause number %d",
range->mm_range_first);
return (0);
}
void
mm_sql_order(mm_command_t *cmd)
{
char *buf = NULL;
char *final_buf = NULL;
char *order_buf = NULL;
mms_trace(MMS_DEVP, "mm_sql_order");
order_buf = mm_sql_order_buf(cmd);
buf = mms_strapp(buf, order_buf);
if (order_buf != NULL)
free(order_buf);
if (buf == NULL) {
return;
}
final_buf = mms_strapp(final_buf, cmd->cmd_buf);
final_buf = mms_strapp(final_buf, buf);
SQL_CHK_LEN(&cmd->cmd_buf, NULL,
&cmd->cmd_bufsize, strlen(final_buf) + 1);
strcpy(cmd->cmd_buf, final_buf);
if (buf)
free(buf);
if (final_buf)
free(final_buf);
return;
no_mem:
MM_ABORT_NO_MEM();
}
char *
mm_sql_order_buf(mm_command_t *cmd)
{
mms_par_node_t *order;
mms_par_node_t *ops;
mms_par_node_t *object;
mms_par_node_t *attr;
mms_par_node_t *work = NULL;
int ordercnt = 0;
char *sql_ops;
char *buf = NULL;
int need_int_cast = 0;
mms_trace(MMS_DEVP, "mm_sql_order_buf");
for (order = mms_pn_lookup(cmd->cmd_root, "order",
MMS_PN_CLAUSE, &work);
order != NULL;
ordercnt++,
order = mms_pn_lookup(cmd->cmd_root, "order",
MMS_PN_CLAUSE, &work)) {
if (ordercnt == 0) {
buf = mms_strapp(buf, "ORDER BY ");
} else {
buf = mms_strapp(buf, ", ");
}
ops = mms_list_head(&order->pn_arglist);
sql_ops = mm_sql_get_ops(ops->pn_string);
mms_trace(MMS_DEVP,
"op == %s",
ops->pn_string);
if ((strcmp(ops->pn_string,
"numhilo") == 0) ||
(strcmp(ops->pn_string,
"numlohi") == 0)) {
need_int_cast = 1;
buf = mms_strapp(buf,
"int4(");
}
object = mms_list_head(&ops->pn_arglist);
buf = mms_strapp(buf, "\"%s\".",
object->pn_string);
attr = mms_list_head(&object->pn_arglist);
buf = mms_strapp(buf, "\"%s\" ",
attr->pn_string);
if (need_int_cast) {
buf = mms_strapp(buf, ") ");
}
buf = mms_strapp(buf, "%s", sql_ops);
}
if (buf == NULL) {
mms_trace(MMS_DEVP, "Order buf is NULL");
buf = mms_strapp(buf, " ");
return (buf);
}
return (buf);
no_mem:
MM_ABORT_NO_MEM();
return (NULL);
}
void
mm_sql_db_err_rsp_new(mm_command_t *cmd, mm_db_t *db)
{
int dbstatus;
char *dbmessage;
dbstatus = PQresultStatus(db->mm_db_results);
dbmessage = PQresultErrorMessage(db->
mm_db_results);
free(cmd->cmd_buf);
if ((cmd->cmd_buf = mm_db_sql_err_rsp(dbstatus, dbmessage,
cmd->wka_ptr->wka_conn.cci_language, cmd->cmd_task)) == NULL) {
MM_ABORT_NO_MEM();
return;
}
mm_clear_db(&db->mm_db_results);
}
int
mm_add_match_list(char *str, mms_list_t *list) {
/* Checks is str is already in list */
/* If str exists, do nothing */
/* Else add to list and inc num */
if (mm_in_char_list(list, str)) {
return (1);
}
if (mm_add_char(str, list)) {
mms_trace(MMS_ERR,
"mm_add_match_list: "
"error adding char");
return (1);
}
return (0);
}
int
/* LINTED: mm_wka may be used in the future */
mm_get_const(mm_wka_t *mm_wka, mm_command_t *cmd)
{
mms_par_node_t *match;
mms_par_node_t *node;
int off = 0;
mms_par_node_t *vol_name;
mms_trace(MMS_DEVP, "mm_get_const");
if (cmd->cmd_buf != NULL) {
free(cmd->cmd_buf);
cmd->cmd_buf = NULL;
cmd->cmd_bufsize = 0;
}
/* Look up the match clause */
match = mms_pn_lookup(cmd->cmd_root, "match",
MMS_PN_CLAUSE, NULL);
if (match == NULL) {
/* No match clause, chek for volname */
vol_name = mms_pn_lookup(cmd->cmd_root, "volname",
MMS_PN_CLAUSE, NULL);
if (vol_name != NULL) {
/* Found a volname */
mm_sql_trans_volname(cmd, &off);
} else {
/* No match and no volname */
return (1);
}
if (cmd->cmd_buf != NULL) {
mms_trace(MMS_DEVP, "cmd_buf is \n%s\n", cmd->cmd_buf);
}
mms_trace(MMS_DEVP, "cmd_const_num = %d", cmd->cmd_const_num);
if (mm_add_char(cmd->cmd_buf,
&cmd->cmd_const_list)) {
mms_trace(MMS_ERR, "Error adding char to const list"
"- out of memory");
return (1);
}
cmd->cmd_const_num ++;
return (0);
}
/* We have a match clause */
node = mms_list_head(&match->pn_arglist);
if (node == NULL) {
mms_trace(MMS_ERR, "Error translating match expression");
return (1);
}
if (mm_sql_trans_match_exp(node, cmd, &off, 0)) {
mms_trace(MMS_ERR, "Error translating match expression");
return (1);
}
/* List way */
if (mm_add_char(cmd->cmd_buf,
&cmd->cmd_const_list)) {
mms_trace(MMS_ERR, "Error adding char to source list");
return (1);
}
/* Array Way */
cmd->cmd_const_num ++;
/* List TEST */
mms_trace(MMS_DEVP, "Printing char_list const...");
mm_print_char_list(&cmd->cmd_const_list);
return (0);
no_mem:
MM_ABORT_NO_MEM();
return (MM_CMD_ERROR);
}
int
/* LINTED: mm_wka may be used in the future */
mm_get_source(mm_wka_t *mm_wka, mm_command_t *cmd)
{
mms_par_node_t *report;
mms_par_node_t *object;
mms_par_node_t *work;
int source_count = 0;
int skip = 0;
mms_trace(MMS_DEBUG, "mm_get_source");
report = mms_pn_lookup(cmd->cmd_root, "report",
MMS_PN_CLAUSE, NULL);
if (report == NULL) {
cmd->cmd_source_num = 0;
return (1);
}
work = NULL;
for (object = mms_pn_lookup(report, NULL, MMS_PN_OBJ, &work);
object != NULL;
object = mms_pn_lookup(report, NULL, MMS_PN_OBJ, &work)) {
skip = 0;
if (mm_in_char_list(&cmd->cmd_source_list,
object->pn_string)) {
/* already have this as a source */
skip = 1;
}
if (!skip) {
/* List way */
if (mm_add_char(object->pn_string,
&cmd->cmd_source_list)) {
mms_trace(MMS_ERR, "Error adding "
"char to source list");
return (1);
}
/* Array Way */
source_count ++;
}
}
cmd->cmd_source_num = source_count;
/* List TEST */
mms_trace(MMS_DEVP, "Printing char_list source...");
mm_print_char_list(&cmd->cmd_source_list);
return (0);
}
void
mm_get_dest_helper(mms_par_node_t *node, mm_command_t *cmd)
{
mms_par_node_t *arg;
int skip = 0;
if (node->pn_type == MMS_PN_OBJ) {
if (node->pn_string != NULL) {
skip = 0;
if (mm_in_char_list(&cmd->cmd_dest_list,
node->pn_string)) {
/* already have this as a dest */
skip = 1;
}
if (!skip) {
/* List way */
if (mm_add_char(node->pn_string,
&cmd->cmd_dest_list)) {
mms_trace(MMS_ERR, "Error adding "
"char to source list");
}
/* Array Way */
cmd->cmd_dest_num ++;
}
}
arg = mms_list_head(&node->pn_arglist);
} else if (node->pn_flags & MMS_PN_MULTIOPS) {
if (node->pn_flags & MMS_PN_REGEX) {
/* sql regular expression is at end of list */
arg = mms_list_head(&node->pn_arglist);
mms_list_remove(&node->pn_arglist, arg);
mms_list_insert_tail(&node->pn_arglist, arg);
}
mms_list_foreach(&node->pn_arglist, arg) {
mm_get_dest_helper(arg, cmd);
}
if (node->pn_flags & MMS_PN_REGEX) {
/* restore list to original order */
arg = mms_list_tail(&node->pn_arglist);
mms_list_remove(&node->pn_arglist, arg);
mms_list_insert_head(&node->pn_arglist, arg);
}
} else if (node->pn_flags & MMS_PN_UNARYOPS) {
if (strcmp(node->pn_string, "isattr") == 0 ||
strcmp(node->pn_string, "noattr") == 0) {
arg = mms_list_head(&node->pn_arglist);
} else {
arg = mms_list_head(&node->pn_arglist);
mm_get_dest_helper(arg, cmd);
}
}
}
void
mm_clear_const(mm_command_t *cmd) {
mm_free_list(&cmd->cmd_const_list);
cmd->cmd_const_num = 0;
}
void
mm_clear_dest(mm_command_t *cmd) {
mm_free_list(&cmd->cmd_dest_list);
cmd->cmd_dest_num = 0;
}
void
mm_clear_source(mm_command_t *cmd) {
mm_free_list(&cmd->cmd_source_list);
cmd->cmd_source_num = 0;
}
int
/* LINTED: mm_wka may be used in the future */
mm_get_dest(mm_wka_t *mm_wka, mm_command_t *cmd)
{
mms_par_node_t *match;
mms_par_node_t *node;
mms_par_node_t *vol_name;
mms_trace(MMS_DEVP, "mm_get_dest");
match = mms_pn_lookup(cmd->cmd_root, "match",
MMS_PN_CLAUSE, NULL);
if (match == NULL) {
vol_name = mms_pn_lookup(cmd->cmd_root, "volname",
MMS_PN_CLAUSE, NULL);
if (vol_name != NULL) {
/* List way */
if (mm_add_char("VOLUME",
&cmd->cmd_dest_list)) {
mms_trace(MMS_ERR, "Error adding "
"char to source list");
}
/* Array Way */
cmd->cmd_dest_num ++;
return (0);
}
return (1);
}
mms_list_foreach(&match->pn_arglist, node) {
mm_get_dest_helper(node, cmd);
}
/* List TEST */
mms_trace(MMS_DEVP, "Printing char_list dest...");
mm_print_char_list(&cmd->cmd_dest_list);
return (0);
}
int
mm_non_priv_const(mm_wka_t *mm_wka, mm_command_t *cmd) {
char *const_buf = NULL;
mms_list_t *source_list = &cmd->cmd_source_list;
cci_t *conn = &mm_wka->wka_conn;
char *app_name = conn->cci_client;
/*
* Cartridge/volume constriants
*/
/* Check for the objects in the source list */
if (mm_in_char_list(source_list, "CARTRIDGE") ||
mm_in_char_list(source_list, "PARTITION") ||
mm_in_char_list(source_list, "SIDE") ||
mm_in_char_list(source_list, "SLOT") ||
mm_in_char_list(source_list, "CARTRIDGEGROUP") ||
mm_in_char_list(source_list, "CARTRIDGEGROUPAPPLICATION")) {
/* Add constraint for CARTRIDGE */
(void) mm_add_to_dest(cmd,
"CARTRIDGEGROUPAPPLICATION");
if (const_buf)
free(const_buf);
const_buf = NULL;
const_buf = mms_strapp(const_buf,
"\"CARTRIDGEGROUPAPPLICATION\"."
"\"ApplicationName\" = '%s'",
app_name);
(void) mm_add_to_const(cmd, const_buf);
}
if (mm_in_char_list(source_list, "VOLUME")) {
/* Add constraint for VOLUME */
(void) mm_add_to_dest(cmd,
"VOLUME");
if (const_buf)
free(const_buf);
const_buf = NULL;
const_buf = mms_strapp(const_buf,
"\"VOLUME\"."
"\"ApplicationName\" = '%s'",
app_name);
(void) mm_add_to_const(cmd, const_buf);
}
/*
* Drive/Mount constraints
*/
if (mm_in_char_list(source_list, "DRIVE") ||
mm_in_char_list(source_list, "DRIVEGROUP") ||
mm_in_char_list(source_list, "DRIVEGROUPAPPLICATION") ||
mm_in_char_list(source_list, "DM") ||
mm_in_char_list(source_list, "DMCAPABILITY") ||
mm_in_char_list(source_list, "DMCAPABILITYTOKEN") ||
mm_in_char_list(source_list, "DMCAPABILITYDEFAULTTOKEN") ||
mm_in_char_list(source_list, "DMCAPABILITYGROUP") ||
mm_in_char_list(source_list, "DMCAPABILITYGROUPTOKEN") ||
mm_in_char_list(source_list, "DMBITFORMAT") ||
mm_in_char_list(source_list, "DMBITFORMATTOKEN")) {
/* Add constraint for DRIVE */
(void) mm_add_to_dest(cmd,
"DRIVEGROUPAPPLICATION");
if (const_buf)
free(const_buf);
const_buf = NULL;
const_buf = mms_strapp(const_buf,
"\"DRIVEGROUPAPPLICATION\"."
"\"ApplicationName\" = '%s'",
app_name);
(void) mm_add_to_const(cmd, const_buf);
}
if (mm_in_char_list(source_list, "MOUNTPHYSICAL") ||
mm_in_char_list(source_list, "MOUNTLOGICAL") ||
mm_in_char_list(source_list, "STALEHANDLE")) {
/* Add constraint for MOUNTPHYSICAL */
(void) mm_add_to_dest(cmd,
"MOUNTPHYSICAL");
if (const_buf)
free(const_buf);
const_buf = NULL;
const_buf = mms_strapp(const_buf,
"\"MOUNTPHYSICAL\"."
"\"ApplicationName\" = '%s'",
app_name);
(void) mm_add_to_const(cmd, const_buf);
}
/*
* System/connection constraints
*/
if (mm_in_char_list(source_list, "APPLICATION") ||
mm_in_char_list(source_list, "AI")) {
/* Add constraint for APPLICATION */
(void) mm_add_to_dest(cmd,
"APPLICATION");
if (const_buf)
free(const_buf);
const_buf = NULL;
const_buf = mms_strapp(const_buf,
"\"APPLICATION\"."
"\"ApplicationName\" = '%s'",
app_name);
(void) mm_add_to_const(cmd, const_buf);
}
if (mm_in_char_list(source_list, "CONNECTION") ||
mm_in_char_list(source_list, "SESSION") ||
mm_in_char_list(source_list, "NOTIFY")) {
/* Add constraint for DRIVE */
(void) mm_add_to_dest(cmd,
"CONNECTION");
if (const_buf)
free(const_buf);
const_buf = NULL;
const_buf = mms_strapp(const_buf,
"\"CONNECTION\"."
"\"ConnectionClientName\" = '%s'",
app_name);
(void) mm_add_to_const(cmd, const_buf);
}
if (const_buf)
free(const_buf);
const_buf = NULL;
return (0);
}
void
mm_path_match_report(mm_command_t *cmd, mm_db_t *db)
{
int off;
mms_par_node_t *report;
mms_par_node_t *reportmode;
mms_par_node_t *object;
mms_par_node_t *attr;
mms_par_node_t *work;
mm_wka_t *mm_wka = cmd->wka_ptr;
mms_trace(MMS_DEVP, "mm_path_match_report");
report = mms_pn_lookup(cmd->cmd_root, "report",
MMS_PN_CLAUSE, NULL);
if (report == NULL) {
SQL_CHK_LEN(&cmd->cmd_buf, 0, &cmd->cmd_bufsize,
strlen(RESPONSE_SUCCESS) +
strlen(cmd->cmd_task) + 1);
(void) snprintf(cmd->cmd_buf, cmd->cmd_bufsize,
RESPONSE_SUCCESS, cmd->cmd_task);
return;
}
mm_clear_source(cmd);
if (mm_get_source(mm_wka, cmd)) {
/* Command does not have a report clause */
mms_trace(MMS_DEVP, "No report clause");
} else {
/* TEMP - Trace out our source info */
mms_trace(MMS_DEVP, "Source count is %d", cmd->cmd_source_num);
mm_print_char_list(&cmd->cmd_source_list);
}
mm_clear_dest(cmd);
if (mm_get_dest(mm_wka, cmd)) {
/* Command does not have a match/volname clause */
mms_trace(MMS_DEVP, "No match/volname Clause");
} else {
/* TEMP - Trace out our dest info */
mms_trace(MMS_DEVP, "Dest count is %d", cmd->cmd_dest_num);
mm_print_char_list(&cmd->cmd_dest_list);
}
/* Build Constraint List */
mm_clear_const(cmd);
if (mm_get_const(mm_wka, cmd)) {
/* Command does not have a match/volname clause */
mms_trace(MMS_DEVP, "No match/volname Clause???");
} else {
/* TEMP - Trace out our const info */
mms_trace(MMS_DEVP, "Const count is %d", cmd->cmd_const_num);
mm_print_char_list(&cmd->cmd_const_list);
}
/* For non priv-clients, check the source list */
/* Add any additional constraits necessary */
/* ie. VOLUME.ApplicationName = cci_client */
/* both source + dest may need adds */
if (cmd->wka_ptr->wka_privilege == MM_PRIV_STANDARD) {
mms_trace(MMS_DEVP,
"add non-priv constraints");
/* Need to check source list and */
/* add constraints as necessary */
if (mm_non_priv_const(mm_wka, cmd)) {
mms_trace(MMS_ERR,
"error adding non-priv "
"client constraints");
}
mms_trace(MMS_DEVP,
"const list after additions, %d",
cmd->cmd_const_num);
mm_print_char_list(&cmd->cmd_const_list);
} else {
mms_trace(MMS_DEVP,
"skip constraints forpriv client");
}
SQL_CHK_LEN(&cmd->cmd_buf, 0, &cmd->cmd_bufsize, 7);
off = snprintf(cmd->cmd_buf, cmd->cmd_bufsize, "SELECT ");
/* If unique is specified in the reportmode clause, insert DISTINCT */
reportmode = mms_pn_lookup(cmd->cmd_root, "reportmode",
MMS_PN_CLAUSE, NULL);
if (reportmode && mms_pn_lookup(reportmode, "unique",
MMS_PN_KEYWORD, NULL)) {
SQL_CHK_LEN(&cmd->cmd_buf, off, &cmd->cmd_bufsize, 9);
off += snprintf(cmd->cmd_buf + off, cmd->cmd_bufsize - off,
"DISTINCT ");
}
work = NULL;
for (object = mms_pn_lookup(report, NULL, MMS_PN_OBJ, &work);
object != NULL;
object = mms_pn_lookup(report, NULL, MMS_PN_OBJ, &work)) {
attr = mms_pn_lookup(object, NULL, MMS_PN_ATTR, NULL);
if (attr == NULL) {
/* show all attributes */
SQL_CHK_LEN(&cmd->cmd_buf, off, &cmd->cmd_bufsize,
4 + strlen(object->pn_string));
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off,
"\"%s\".*,", object->pn_string);
} else {
/*
* More than one object column reference can't be be
* ambiguous, specify object and attribute.
*/
SQL_CHK_LEN(&cmd->cmd_buf, off, &cmd->cmd_bufsize,
6 + strlen(object->pn_string) +
strlen(object->pn_string) +
strlen(attr->pn_string));
off += snprintf(cmd->cmd_buf + off,
cmd->cmd_bufsize - off,
"\"%s\".\"%s\",",
object->pn_string,
attr->pn_string);
}
}
off--; /* overwrite the last comma */
SQL_CHK_LEN(&cmd->cmd_buf, off, &cmd->cmd_bufsize, 6);
off += snprintf(cmd->cmd_buf + off, cmd->cmd_bufsize - off, " FROM ");
if (mm_sql_from_where(cmd, db)) {
mms_trace(MMS_ERR,
"mm_path_match_report: "
"db error creating helper functions");
return;
}
mm_sql_order(cmd);
mm_sql_number(cmd);
if (mm_sql_report(cmd)) {
mms_trace(MMS_ERR,
"mm_path_match_report: "
"error generating final response");
}
return;
no_mem:
MM_ABORT_NO_MEM();
return;
not_found:
mm_response_error(cmd,
ECLASS_LANGUAGE,
ENOTFOUND,
5062,
MESS_END);
return;
}
/*
* function to set a LM/DM/DRIVE/LIBRARY state
* uses its own db connection
* to set drive 1, DRIVE.DriveStateHard to 'loaded' :
* mm_sql_update_state(&mm_data, "DRIVE", "DriveStateHard", "loaded",
* "DriveName", "drive1");
*/
#define MM_SQL_UPDATE_STATE "update \"%s\" "\
"set \"%s\" = '%s' "\
"where \"%s\" = '%s';"
void
mm_sql_update_state(mm_data_t *data, char *object, char *attribute,
char *value, char *instance, char *name)
{
mm_db_t *db = &data->mm_db;
if (mm_db_exec(HERE, db, MM_SQL_UPDATE_STATE,
object, attribute, value,
instance, name) != MM_DB_OK) {
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
mms_trace(MMS_ERR,
"mm_sql_update_state: "
"db error updating db states");
}
return;
}
int
/* LINTED: db is used by this function */
mm_system_settings(mm_db_t *db, int *request_oper, int *auto_clear) {
#if 1
/* TEMP - dont request, always clear */
*auto_clear = 1;
*request_oper = 0;
return (0);
#else
rc = mm_db_exec(HERE, db,
"select "
"\"AskClearDriveAtLMConfig\","
"\"ClearDriveAtLMConfig\" "
"from \"SYSTEM\";");
if (rc != MM_DB_DATA) {
mms_trace(MMS_ERR, "Db error in mm_clear_unknown_tape");
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
return (1);
}
if (PQntuples(db->mm_db_results) < 1) {
mms_trace(MMS_ERR, "Missing SYSTEM object");
return (1);
}
mms_trace(MMS_DEVP, "AskClearDrive = %s, ClearDrive = %s",
PQgetvalue(db->mm_db_results, 0, 0),
PQgetvalue(db->mm_db_results, 0, 1));
if (strcmp(PQgetvalue(db->mm_db_results, 0, 0),
"yes") == 0) {
*request_oper = 1;
}
/* Don't ask the oper */
if (strcmp(PQgetvalue(db->mm_db_results, 0, 1),
"yes") == 0) {
*auto_clear = 1;
}
return (0);
#endif
}
int
/* LINTED: a mm_wka arg is required by all cmd functions */
mm_req_test_cmd_func(mm_wka_t *mm_wka, mm_command_t *cmd) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
mms_trace(MMS_DEVP, "mm_req_test_cmd_func");
mms_trace(MMS_DEVP, "request clear for %s, %s",
mount_info->cmi_drive, mount_info->cmi_cartridge);
return (MM_DEPEND_DONE);
}
int
mm_add_clear_request(mm_wka_t *mm_wka, mm_command_t *cmd) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
mm_command_t *req_cmd;
mm_wka_t *oper_wka;
mm_data_t *mm_data = mm_wka->mm_data;
uuid_text_t uuid;
mms_trace(MMS_DEVP, "adding clear drive request,"
"drive %s, cartridge %s",
mount_info->cmi_drive, mount_info->cmi_cartridge);
oper_wka = NULL;
mms_list_foreach(&mm_data->mm_wka_list, oper_wka) {
if ((strcmp(oper_wka->wka_conn.cci_instance,
"oper") == 0) &&
(strcmp(oper_wka->wka_conn.cci_client,
"MMS") == 0)) {
/* Found the wka of oper */
break;
}
}
if (oper_wka == NULL) {
mms_trace(MMS_DEBUG, "operator not connected");
return (1);
}
if ((req_cmd = mm_alloc_cmd(oper_wka)) == NULL) {
mms_trace(MMS_ERR,
"Unable to malloc mm_command_t: %s",
strerror(errno));
return (1);
}
mm_add_depend(req_cmd, cmd);
mm_get_uuid(uuid);
req_cmd->cmd_root = NULL;
req_cmd->cmd_task = NULL;
req_cmd->cmd_task = strdup(uuid);
if (req_cmd->cmd_task == NULL) {
mms_trace(MMS_ERR, "Error malloc cmd_task in add cmd");
return (MM_CMD_ERROR);
}
req_cmd->cmd_func = mm_req_test_cmd_func;
req_cmd->cmd_name = strdup("clear drive oper request");
req_cmd->cmd_mount_info.cmi_drive = strdup(mount_info->cmi_drive);
req_cmd->cmd_mount_info.cmi_cartridge =
strdup(mount_info->cmi_cartridge);
mms_list_insert_tail(&mm_data->mm_cmd_queue, req_cmd);
return (0);
}
extern int mm_errorcode_eq(mms_par_node_t *cmd_response, char *code) {
/* This function takes an MMP/DMP/LMP */
/* response and returns a pointer to the error code */
mm_response_t response;
if (mm_parse_response(cmd_response, &response) == 1) {
mms_trace(MMS_ERR,
"Error parsing command response");
return (0);
}
if ((response.error_class == NULL) ||
(response.error_code == NULL)) {
/* Might not be an error response */
return (0);
}
if (strcmp(response.error_code, code) == 0) {
return (1);
}
return (0);
}
int
mm_non_physical_clear_cmd_func(mm_wka_t *mm_wka, mm_command_t *cmd) {
mm_db_t *db = &cmd->cmd_mm_data->mm_db;
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
/* 1. DMP detach */
/* 2. DMP release */
/* 3. Schedule delay unmount/unload */
if (cmd->cmd_state == 0) {
mms_trace(MMS_DEVP,
"non-physical clear, add detach");
/* Need both drive and dm set */
if ((mount_info->cmi_drive == NULL)) {
mms_trace(MMS_ERR,
"cmi_drive/dm is NULL for "
"this non-physical clear");
return (MM_CMD_ERROR);
}
/* Get DM Name */
if (mm_db_exec(HERE, db,
"select \"DMName\" from \"DRIVE\" "
"where \"DRIVE\".\"DriveName\" = '%s';",
mount_info->cmi_drive) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"db error");
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
return (MM_CMD_ERROR);
}
if (PQntuples(db->mm_db_results) != 1) {
mms_trace(MMS_ERR,
"row num mismatch");
mm_clear_db(&db->mm_db_results);
return (MM_CMD_ERROR);
}
if (strcmp(PQgetvalue(db->mm_db_results, 0, 0), "") == 0) {
mms_trace(MMS_ERR,
"missing dm name");
mm_clear_db(&db->mm_db_results);
return (MM_CMD_ERROR);
}
mm_set_mount_info_dm(PQgetvalue(db->mm_db_results, 0, 0),
mount_info);
mm_clear_db(&db->mm_db_results);
/* Send a detach */
if (mm_dmp_add_cmd(mm_wka, cmd, mount_info->cmi_dm,
MM_DMP_DETACH) == NULL) {
mms_trace(MMS_ERR,
"mm_non_physical_clear_cmd_func: "
"error adding dmp detach");
}
cmd->cmd_state = 1;
return (MM_DISPATCH_DEPEND);
}
if (cmd->cmd_state == 1) {
mms_trace(MMS_DEVP,
"non-physical clear, add release");
/*
* Detach has returned
* check error, update states
* Add Unload command
*/
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
if ((cmd->cmd_response != NULL) &&
mm_errorcode_eq(cmd->cmd_response,
"DM_E_NOEXISTHANDLE")) {
mms_trace(MMS_DEVP,
"DM doesn't know the handle, "
"skip DMP unload, "
"send LMP unmount");
/* Clear depend error flags */
MM_UNSET_FLAG(cmd->cmd_flags,
MM_CMD_DEPEND_ERROR);
} else {
/* detach returned handle in use */
mms_trace(MMS_ERR,
"non-physical clear_drive -> "
"DMP detach error, "
"handle may be inuse");
return (MM_CMD_ERROR);
}
}
mms_trace(MMS_DEVP,
"DM is not using handle, send DMP release");
if (mm_dmp_add_cmd(mm_wka, cmd, mount_info->cmi_dm,
MM_DMP_RELEASE) == NULL) {
mms_trace(MMS_ERR,
"mm_non_physical_clear_cmd_func: "
"error adding dmp release");
}
cmd->cmd_state = 2;
return (MM_DISPATCH_DEPEND);
}
if (cmd->cmd_state == 2) {
mms_trace(MMS_DEVP,
"non-physical clear, schedule unload");
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
/* unload returned an error */
mms_trace(MMS_ERR, "clear_drive -> DMP release error");
}
if (mm_db_exec(HERE, db,
"select distinct \"CARTRIDGE\"."
"\"CartridgeID\" from \"CARTRIDGE\""
"cross join \"DRIVE\""
"where"
"((\"CARTRIDGE\".\"LibraryName\" "
"= \"DRIVE\".\"LibraryName\")"
"and"
"(\"DRIVE\".\"DriveName\" = '%s')"
"and"
"(\"CARTRIDGE\".\"CartridgePCL\" = "
"\"DRIVE\".\"CartridgePCL\"));",
mount_info->cmi_drive) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"db error");
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
return (MM_CMD_ERROR);
}
if (PQntuples(db->mm_db_results) != 1) {
mms_trace(MMS_ERR,
"row num mismatch");
mm_clear_db(&db->mm_db_results);
return (MM_CMD_ERROR);
}
mm_set_mount_info_cart(PQgetvalue(db->mm_db_results, 0, 0),
mount_info);
mm_clear_db(&db->mm_db_results);
if (mm_db_exec(HERE, db, "delete from \"TASKCARTRIDGE\""
"where \"TaskID\" = '%s';", cmd->cmd_uuid) != MM_DB_OK) {
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
mms_trace(MMS_ERR,
"mm_non_physical_clear_cmd_func: "
"db error deleting TASKCARTRIDGE");
}
if (mm_db_exec(HERE, db, "delete from \"TASKDRIVE\" "
"where \"TaskID\" = '%s';", cmd->cmd_uuid) != MM_DB_OK) {
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
mms_trace(MMS_ERR,
"mm_non_physical_clear_cmd_func: "
"db error deleting TASKDRIVE");
}
if (mm_db_exec(HERE, db, "delete from \"TASKLIBRARY\" "
"where \"TaskID\" = '%s';", cmd->cmd_uuid) != MM_DB_OK) {
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
mms_trace(MMS_ERR,
"mm_non_physical_clear_cmd_func: "
"db error deleting TASKLIBRARY");
}
if (mm_db_exec(HERE, db, "delete from \"TASK\" "
"where \"TaskID\" = '%s';", cmd->cmd_uuid) != MM_DB_OK) {
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
mms_trace(MMS_ERR,
"mm_non_physical_clear_cmd_func: "
"db error deleting TASK");
}
if (mm_db_exec(HERE, db, "delete from \"MOUNTLOGICAL\" "
"where \"CartridgeID\" = '%s';",
mount_info->cmi_cartridge) != MM_DB_OK) {
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
mms_trace(MMS_ERR,
"mm_non_physical_clear_cmd_func: "
"db error deleting MOUNTLOGICAL");
}
if (mm_db_exec(HERE, db, "delete from \"MOUNTPHYSICAL\" "
"where \"CartridgeID\" = '%s';",
mount_info->cmi_cartridge) != MM_DB_OK) {
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
mms_trace(MMS_ERR,
"mm_non_physical_clear_cmd_func: "
"db error deleting MOUNTPHYSICAL");
}
if (mm_schedule_unload(mm_wka, cmd)) {
mms_trace(MMS_ERR,
"mm_non_physical_clear_cmd_func: "
"error scheduling delay unload");
}
cmd->cmd_remove = 1;
mms_trace(MMS_DEVP,
"non-physical clear complete, delay unload scheduled");
return (MM_DISPATCH_AGAIN);
}
mms_trace(MMS_ERR,
"mm_non_physical_clear_cmd_func: unknown cmd state");
return (MM_CMD_ERROR);
}
#define MM_CLEAR_START 0
#define MM_CLEAR_SLOTSCAN 20
#define MM_CLEAR_DETACH 21
#define MM_CLEAR_RELEASE 22
#define MM_CLEAR_UNLOAD 23
#define MM_CLEAR_UNMOUNT 24
#define MM_CLEAR_FINAL 25
int
mm_clear_drive_cmd_func(mm_wka_t *mm_wka, mm_command_t *cmd) {
mm_db_t *db = &cmd->cmd_mm_data->mm_db;
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
mm_data_t *data = cmd->cmd_mm_data;
int rc;
mm_command_t *lmp_umnt_cmd;
uuid_text_t new_task;
/* This is a physical unmount */
/* detach, release, unload, unmount */
start:
if (cmd->cmd_state == MM_CLEAR_START) {
/* Clear depend error flags, */
/* On the 1st cmd state of clear drive */
/* ignore any errors */
/* This clear drive may be running after */
/* A DMP activate which may have errored */
/* Try to clear anyways */
MM_UNSET_FLAG(cmd->cmd_flags,
MM_CMD_DEPEND_ERROR);
if (mount_info->cmi_library == NULL) {
mms_trace(MMS_ERR,
"library name not set for clear drive");
return (MM_CMD_ERROR);
}
/* Confirm LM is connected and active */
rc = mm_db_exec(HERE, db,
"select distinct "
"\"LM\".\"LMStateSoft\" from \"LM\""
"cross join \"LIBRARY\""
"where((\"LM\".\"LibraryName\" = "
"\"LIBRARY\".\"LibraryName\")"
"and(\"LIBRARY\".\"LibraryName\" = '%s'));",
mount_info->cmi_library);
if (rc != MM_DB_DATA) {
mms_trace(MMS_ERR, "Exec returned with no Data");
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
return (MM_CMD_ERROR);
}
if (PQntuples(db->mm_db_results) == 0) {
mms_trace(MMS_ERR,
"library, %s, has no lm assigned",
mount_info->cmi_library);
mm_clear_db(&db->mm_db_results);
return (MM_CMD_ERROR);
}
if (strcmp(PQgetvalue(db->mm_db_results, 0, 0),
"not ready") == 0) {
mms_trace(MMS_DEVP, "lm is not ready, wait");
MM_SET_FLAG(cmd->cmd_flags, MM_CMD_DISPATCHABLE);
mm_clear_db(&db->mm_db_results);
return (MM_NO_DISPATCH);
}
if (strcmp(PQgetvalue(db->mm_db_results, 0, 0), "ready") == 0) {
mms_trace(MMS_DEVP, "lm ready, continue");
} else {
mms_trace(MMS_ERR,
"lm state = %s, cancel clear drive",
PQgetvalue(db->mm_db_results, 0, 0));
mm_clear_db(&db->mm_db_results);
return (MM_CMD_ERROR);
}
mm_clear_db(&db->mm_db_results);
mms_trace(MMS_DEBUG, "LM Ready, try to clear "
"drive -> %s, send scan",
mount_info->cmi_drive);
/* Add LMP scan command for this drive */
if (mm_add_lmp_scan(mm_wka->mm_data, cmd,
mount_info->cmi_drive,
NULL, mount_info->cmi_library)) {
mms_trace(MMS_ERR,
"Error adding LMP scan");
return (MM_CMD_ERROR);
} else {
mms_trace(MMS_DEBUG,
"Added LMP scan");
cmd->cmd_state = MM_CLEAR_DETACH;
}
/* If DRIVE is occupied and has pcl set */
/* MM will need to send lmp scan for the */
/* cartridge as well */
if (mount_info->cmi_pcl != NULL) {
mms_trace(MMS_DEVP,
"cmi_pcl already set, %s",
mount_info->cmi_pcl);
cmd->cmd_state = MM_CLEAR_SLOTSCAN;
return (MM_DISPATCH_DEPEND);
}
/* set mount_info->cmi_pcl */
if (mm_db_exec(HERE, db,
"select distinct "
"\"DRIVE\".\"CartridgePCL\""
"from \"DRIVE\" "
"where"
" \"DRIVE\".\"DriveName\" = '%s'; ",
mount_info->cmi_drive) != MM_DB_DATA) {
mms_trace(MMS_ERR, "Couldn't get Cartridge_PCL -> "
"mm_clear_drive_cmd_func");
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
return (MM_CMD_ERROR);
}
if (PQntuples(db->mm_db_results) == 0) {
mms_trace(MMS_ERR,
"error getting pcl from drive");
mm_clear_db(&db->mm_db_results);
return (MM_CMD_ERROR);
}
if (strcmp(PQgetvalue(db->mm_db_results,
0, 0), MM_NON_MMS_CART) == 0) {
mms_trace(MMS_DEVP,
"drive loaded with non-mms cart");
/* If non-mms cart return */
/* since this is not part of MMS */
/* MM does not need a cart scan */
mm_clear_db(&db->mm_db_results);
return (MM_DISPATCH_DEPEND);
}
if (strcmp(PQgetvalue(db->mm_db_results,
0, 0), "") != 0) {
/* DRIVE.pcl was set */
cmd->cmd_state = MM_CLEAR_SLOTSCAN;
mm_set_mount_info_pcl(PQgetvalue(db->
mm_db_results, 0, 0),
mount_info);
}
mm_clear_db(&db->mm_db_results);
return (MM_DISPATCH_DEPEND);
}
if (cmd->cmd_state == MM_CLEAR_SLOTSCAN) {
/* Command state when a lmp scan for slot is needed */
/* Drive scan has completed */
mms_trace(MMS_DEVP,
"drive scan complete, send scan of PCL");
/* Add LMP scan command for this drive */
if (mm_add_lmp_scan(mm_wka->mm_data, cmd,
NULL, mount_info->cmi_pcl,
mount_info->cmi_library)) {
mms_trace(MMS_ERR,
"Error adding LMP scan");
return (MM_CMD_ERROR);
} else {
mms_trace(MMS_DEBUG,
"Added LMP scan");
cmd->cmd_state = MM_CLEAR_DETACH;
}
if (mount_info->cmi_pcl != NULL) {
free(mount_info->cmi_pcl);
mount_info->cmi_pcl = NULL;
}
return (MM_DISPATCH_DEPEND);
}
if (cmd->cmd_state == MM_CLEAR_DETACH) {
/* Send the DMP detach command */
mms_trace(MMS_DEVP,
"physical clear, add detach");
/* Need drive set */
if ((mount_info->cmi_drive == NULL)) {
mms_trace(MMS_ERR,
"cmi_drive is NULL for "
"this physical clear");
return (MM_CMD_ERROR);
}
/* set mount_info->cmi_pcl */
if (mm_db_exec(HERE, db,
"select distinct "
"\"DRIVE\".\"CartridgePCL\""
"from \"DRIVE\" "
"where"
" \"DRIVE\".\"DriveName\" = '%s'; ",
mount_info->cmi_drive) != MM_DB_DATA) {
mms_trace(MMS_ERR, "Couldn't get Cartridge_PCL -> "
"mm_clear_drive_cmd_func");
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
return (MM_CMD_ERROR);
}
if (PQntuples(db->mm_db_results) == 0) {
mms_trace(MMS_ERR,
"error getting pcl from drive");
mm_clear_db(&db->mm_db_results);
return (MM_CMD_ERROR);
}
if (strcmp(PQgetvalue(db->mm_db_results,
0, 0), "") == 0) {
mms_trace(MMS_DEVP,
"LMP scan of drive shows %s is clear",
mount_info->cmi_drive);
mms_trace(MMS_INFO, "%s Cleared Successfully",
mount_info->cmi_drive);
/* Set States For a Clear Drive */
if (mm_db_exec(HERE, db,
"update \"DRIVE\" set "
"\"DriveStateHard\" = 'unloaded', "
"\"DMName\" = DEFAULT, "
"\"DriveLibraryOccupied\" = 'f' "
"where \"DriveName\" = '%s';",
mount_info->cmi_drive) != MM_DB_OK) {
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
mms_trace(MMS_ERR,
"mm_clear_drive_cmd_func: "
"db error updating DRIVE");
}
/* Delete any mountphysical, mountlogical, */
/* or stalehandle */
if (mm_db_exec(HERE, db,
"delete from \"MOUNTLOGICAL\" "
"where \"DriveName\" = '%s';",
mount_info->cmi_drive) != MM_DB_OK) {
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
mms_trace(MMS_ERR,
"mm_clear_drive_cmd_func: "
"db error deleting MOUNTLOGICAL");
}
if (mm_db_exec(HERE, db,
"delete from \"STALEHANDLE\" "
"where \"DriveName\" = '%s';",
mount_info->cmi_drive) != MM_DB_OK) {
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
mms_trace(MMS_ERR,
"mm_clear_drive_cmd_func: "
"db error deleting STALEHANDLE");
}
if (mm_db_exec(HERE, db,
"delete from \"MOUNTPHYSICAL\" "
"where \"DriveName\" = '%s';",
mount_info->cmi_drive) != MM_DB_OK) {
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
mms_trace(MMS_ERR,
"mm_clear_drive_cmd_func: "
"db error deleting MOUNTPHYSICAL");
}
mm_clear_db(&db->mm_db_results);
db->mm_db_results = NULL;
if (mm_has_depend(cmd)) {
return (MM_DEPEND_DONE);
}
return (MM_CMD_DONE);
}
if (strcmp(PQgetvalue(db->mm_db_results,
0, 0), MM_NON_MMS_CART) == 0) {
mms_trace(MMS_DEVP,
"this is a clear drive for a non-mms cartridge");
/* Look in the response to the scan to */
/* find the pcl in this drive */
if (mount_info->cmi_pcl != NULL) {
mms_trace(MMS_DEVP,
"pcl already set to %s",
mount_info->cmi_pcl);
} else {
mms_trace(MMS_ERR,
"pcl is NULL for a non-MMS cart");
mm_clear_db(&db->mm_db_results);
return (MM_CMD_ERROR);
}
} else {
mm_set_mount_info_pcl(PQgetvalue(db->
mm_db_results, 0, 0),
mount_info);
}
mm_clear_db(&db->mm_db_results);
if (mount_info->cmi_pcl == NULL) {
mms_trace(MMS_ERR,
"pcl is NULL ");
return (MM_CMD_ERROR);
}
mms_trace(MMS_DEVP,
"pcl set to %s",
mount_info->cmi_pcl);
/* Get DM Name */
if (mm_db_exec(HERE, db,
"select \"DMName\" from \"DRIVE\" "
"where \"DRIVE\".\"DriveName\" = '%s';",
mount_info->cmi_drive) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"db error");
return (MM_CMD_ERROR);
}
if (PQntuples(db->mm_db_results) != 1) {
mms_trace(MMS_ERR,
"row num mismatch");
mm_clear_db(&db->mm_db_results);
return (MM_CMD_ERROR);
}
if (strcmp(PQgetvalue(db->mm_db_results, 0, 0), "") == 0) {
mms_trace(MMS_ERR,
"missing dm name in DRIVE, "
"dm may already be detached, check STALEHANDLE");
mm_clear_db(&db->mm_db_results);
/* Try getting DMName from STALEHANDLE */
if (mm_db_exec(HERE, db,
"select \"DMName\" from \"STALEHANDLE\" "
"where \"STALEHANDLE\".\"DriveName\" = '%s';",
mount_info->cmi_drive) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"db error");
return (MM_CMD_ERROR);
}
if (PQntuples(db->mm_db_results) != 1) {
mms_trace(MMS_ERR,
"Can't find STALEHANDLE, continue unmount");
mm_clear_db(&db->mm_db_results);
cmd->cmd_state = MM_CLEAR_UNLOAD;
goto start;
}
}
mm_set_mount_info_dm(PQgetvalue(db->mm_db_results, 0, 0),
mount_info);
mm_clear_db(&db->mm_db_results);
/* Send a detach */
if (mm_dmp_add_cmd(mm_wka, cmd, mount_info->cmi_dm,
MM_DMP_DETACH) == NULL) {
mms_trace(MMS_ERR,
"mm_clear_drive_cmd_func: "
"error adding dmp detach");
}
cmd->cmd_state = MM_CLEAR_RELEASE;
return (MM_DISPATCH_DEPEND);
}
if (cmd->cmd_state == MM_CLEAR_RELEASE) {
/* Send the DMP release command */
mms_trace(MMS_DEVP,
"physical clear, add release");
/*
* Detach has returned
* check error, update states
* Add Unload command
*/
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
if ((cmd->cmd_response != NULL) &&
mm_errorcode_eq(cmd->cmd_response,
"DM_E_NOEXISTHANDLE")) {
mms_trace(MMS_DEVP,
"DM doesn't know the handle, "
"skip DMP unload, "
"send LMP unmount");
/* Clear depend error flags */
MM_UNSET_FLAG(cmd->cmd_flags,
MM_CMD_DEPEND_ERROR);
} else {
/* detach returned handle in use */
mms_trace(MMS_ERR, "physical clear_drive -> "
"DMP detach error, "
"handle may be inuse");
return (MM_CMD_ERROR);
}
}
mms_trace(MMS_DEVP,
"DM is not using handle, send DMP release if dm is ready");
/* Check, if DM is not activated, don't send a release */
if (mm_db_exec(HERE, db,
"select \"DMStateSoft\" from \"DM\" "
"where \"DM\".\"DMName\" = '%s';",
mount_info->cmi_dm) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"db error");
return (MM_CMD_ERROR);
}
if (PQntuples(db->mm_db_results) != 1) {
mms_trace(MMS_ERR,
"Can't find DM, continue unmount");
mm_clear_db(&db->mm_db_results);
return (MM_CMD_ERROR);
}
if ((strcmp(PQgetvalue(db->mm_db_results, 0, 0),
"present") == 0) ||
(strcmp(PQgetvalue(db->mm_db_results, 0, 0),
"absent") == 0) ||
(strcmp(PQgetvalue(db->mm_db_results, 0, 0),
"disconnected") == 0)) {
/* DM cannot process release */
/* Continue to unmount */
mms_trace(MMS_DEVP,
"DMStateSoft = %s, don't send release, "
"continue with unmount",
PQgetvalue(db->mm_db_results, 0, 0));
mm_clear_db(&db->mm_db_results);
cmd->cmd_state = MM_CLEAR_UNLOAD;
goto start;
}
mms_trace(MMS_DEVP,
"DMStateSoft = %s, about to send release",
PQgetvalue(db->mm_db_results, 0, 0));
mm_clear_db(&db->mm_db_results);
if (mm_dmp_add_cmd(mm_wka, cmd, mount_info->cmi_dm,
MM_DMP_RELEASE) == NULL) {
mms_trace(MMS_ERR,
"mm_clear_drive_cmd_func: "
"error adding dmp release");
}
cmd->cmd_state = MM_CLEAR_UNLOAD;
return (MM_DISPATCH_DEPEND);
}
if (cmd->cmd_state == MM_CLEAR_UNLOAD) {
/* Always send a DMP unload before the physicalunmount */
/* If MM knows what DM to send to */
/* Try to send an unload now */
MM_UNSET_FLAG(cmd->cmd_flags,
MM_CMD_DEPEND_ERROR);
if (mount_info->cmi_dm == NULL) {
mms_trace(MMS_ERR,
"didn't find DM Name, "
"skip DMP unload");
cmd->cmd_state = MM_CLEAR_UNMOUNT;
goto start;
}
mms_trace(MMS_DEVP,
"sending %s DMP unload",
mount_info->cmi_dm);
if (mm_dmp_add_cmd(mm_wka, cmd, mount_info->cmi_dm,
MM_DMP_UNLOAD) == NULL) {
mms_trace(MMS_ERR,
"mm_clear_drive_func: "
"error adding dmp unload");
}
cmd->cmd_state = MM_CLEAR_UNMOUNT;
return (MM_DISPATCH_DEPEND);
}
if (cmd->cmd_state == MM_CLEAR_UNMOUNT) {
/* DMP unload has completed, ignore any errors */
/* and continue with the LMP unmount */
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
mms_trace(MMS_ERR,
"error during DMP unload, "
"continue with LMP unmount");
/* Clear depend error flags */
MM_UNSET_FLAG(cmd->cmd_flags,
MM_CMD_DEPEND_ERROR);
}
mms_trace(MMS_DEVP,
"physical clear, add unmount");
mms_trace(MMS_INFO, "Unmounting %s from %s",
mount_info->cmi_pcl,
mount_info->cmi_drive);
/*
* LMP unmount command
*/
/* ********************* */
/* TODO: FIX SIDE NAME!! */
if ((lmp_umnt_cmd = mm_alloc_cmd(mm_wka)) == NULL) {
mms_trace(MMS_ERR,
"Unable to malloc mm_command_t: %s",
strerror(errno));
return (MM_CMD_ERROR);
}
lmp_umnt_cmd->cmd_func = mm_lmp_unmount_cmd_func;
mm_get_uuid(new_task);
lmp_umnt_cmd->cmd_textcmd = mms_strnew(LMP_UNMOUNT, new_task,
mount_info->cmi_pcl,
mount_info->cmi_pcl,
"side 1",
mount_info->cmi_drive,
mount_info->cmi_pcl,
mount_info->cmi_pcl,
"side 1");
mm_set_mount_info_drive(cmd->cmd_mount_info.cmi_drive,
&lmp_umnt_cmd->cmd_mount_info);
lmp_umnt_cmd->cmd_root =
mm_text_to_par_node(lmp_umnt_cmd->cmd_textcmd,
mms_lmpm_parse);
lmp_umnt_cmd->cmd_task = mm_get_task(lmp_umnt_cmd->cmd_root);
mm_add_depend(lmp_umnt_cmd, cmd);
lmp_umnt_cmd->cmd_name = strdup("lmp unmount");
pthread_mutex_lock(&data->mm_queue_mutex);
mms_list_insert_tail(&data->mm_cmd_queue, lmp_umnt_cmd);
pthread_mutex_unlock(&data->mm_queue_mutex);
cmd->cmd_state = MM_CLEAR_FINAL;
return (MM_DISPATCH_DEPEND);
}
if (cmd->cmd_state == MM_CLEAR_FINAL) {
/*
* LMP mount has returned
* check for error,
* Return MM_DEPEND_DONE on success
*/
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
return (MM_CMD_ERROR);
}
mms_trace(MMS_INFO, "%s Cleared Successfully",
mount_info->cmi_drive);
/* Set States For a Clear Drive */
if (mm_db_exec(HERE, db,
"update \"DRIVE\" set "
"\"DriveStateHard\" = 'unloaded', "
"\"DMName\" = DEFAULT, "
"\"DriveLibraryOccupied\" = 'f' "
"where \"DriveName\" = '%s';",
mount_info->cmi_drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_clear_drive_cmd_func: "
"db error updating DRIVE");
}
/* Delete any mountphysical, mountlogical, or stalehandle */
if (mm_db_exec(HERE, db, "delete from \"MOUNTLOGICAL\" "\
"where \"DriveName\" = '%s';",
mount_info->cmi_drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_clear_drive_cmd_func: "
"db error deleting MOUNTLOGICAL");
}
if (mm_db_exec(HERE, db, "delete from \"STALEHANDLE\" "\
"where \"DriveName\" = '%s';",
mount_info->cmi_drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_clear_drive_cmd_func: "
"db error deleting STALEHANDLE");
}
if (mm_db_exec(HERE, db, "delete from \"MOUNTPHYSICAL\" "\
"where \"DriveName\" = '%s';",
mount_info->cmi_drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_clear_drive_cmd_func: "
"db error deleting MOUNTPHYSICAL");
}
if (mm_has_depend(cmd)) {
return (MM_DEPEND_DONE);
}
return (MM_CMD_DONE);
}
mms_trace(MMS_ERR,
"mm_clear_drive_cmd_func: unknown cmd state");
return (MM_CMD_ERROR);
}
mm_command_t *
mm_add_clear_drive(char *drive_name, mm_data_t *mm_data,
mm_db_t *db,
mm_command_t *parent_cmd, char *cart_pcl, int force,
int nonphysical) {
mm_command_t *cmd;
mm_wka_t *lm_wka;
PGresult *lm_name;
uuid_text_t uuid;
mm_command_t *cur_cmd;
mms_trace(MMS_DEVP, "Adding mm_clear_drive_cmd_func");
if (drive_name == NULL) {
mms_trace(MMS_DEBUG,
"mm_add_clear_drive passed null drive_name");
return (NULL);
}
if (mm_data == NULL) {
mms_trace(MMS_DEBUG,
"mm_add_clear_drive passed null mm_data");
return (NULL);
}
if (db == NULL) {
mms_trace(MMS_DEBUG,
"mm_add_clear_drive passed null db pointer");
return (NULL);
}
if (mm_db_exec(HERE, db,
"select \"LMName\", \"LibraryName\" "\
"from \"LM\" " \
"where \"LibraryName\" in "\
"(select \"LibraryName\" from "\
"\"DRIVE\" where \"DriveName\" = '%s');",
drive_name) != MM_DB_DATA) {
mms_trace(MMS_ERR, "Couldn't get LM Name -> " \
"mm_add_clear_drive");
mm_clear_db(&db->mm_db_results);
return (NULL);
}
lm_name = db->mm_db_results;
if (PQntuples(lm_name) == 0) {
mms_trace(MMS_ERR, "Couldn't get LM Name -> " \
"mm_add_clear_drive");
mm_clear_db(&lm_name);
return (NULL);
}
/* Check the queue, if there is already a clear drive, */
/* do not add another */
/* If other is found, return a pointer to that clear drive */
pthread_mutex_lock(&mm_data->mm_queue_mutex);
mms_list_foreach(&mm_data->mm_cmd_queue, cur_cmd) {
if ((cur_cmd->cmd_func == mm_clear_drive_cmd_func) ||
(cur_cmd->cmd_func ==
mm_non_physical_clear_cmd_func)) {
if ((strcmp(cur_cmd->cmd_mount_info.cmi_drive,
drive_name) == 0) &&
(strcmp(cur_cmd->cmd_mount_info.cmi_library,
PQgetvalue(lm_name, 0, 1)) == 0)) {
mms_trace(MMS_ERR,
"already have a clear "
"drive for %s , %s",
drive_name,
PQgetvalue(lm_name, 0, 1));
pthread_mutex_unlock(&mm_data->
mm_queue_mutex);
mm_clear_db(&lm_name);
return (cur_cmd);
}
}
}
pthread_mutex_unlock(&mm_data->mm_queue_mutex);
lm_wka = NULL;
mms_list_foreach(&mm_data->mm_wka_list, lm_wka) {
if (strcmp(lm_wka->wka_conn.cci_instance,
PQgetvalue(lm_name, 0, 0)) == 0) {
/* Found the wka of lm */
break;
}
}
if ((lm_wka == NULL) || (strcmp(lm_wka->wka_conn.cci_instance,
PQgetvalue(lm_name, 0, 0)) != 0)) {
/* bad wka */
mms_trace(MMS_DEBUG, "Could not find a connected LM");
mm_clear_db(&lm_name);
return (NULL);
}
if ((cmd = mm_alloc_cmd(lm_wka)) == NULL) {
mms_trace(MMS_ERR,
"Unable to malloc mm_command_t: %s",
strerror(errno));
mm_clear_db(&lm_name);
return (NULL);
}
if (parent_cmd != NULL) {
mm_add_depend(cmd, parent_cmd);
}
mm_get_uuid(uuid);
cmd->cmd_root = NULL;
cmd->cmd_task = NULL;
cmd->cmd_task = strdup(uuid);
if (cmd->cmd_task == NULL) {
mms_trace(MMS_ERR, "Error malloc cmd_task in add cmd");
mm_clear_db(&lm_name);
return (NULL);
}
if (nonphysical) {
cmd->cmd_func = mm_non_physical_clear_cmd_func;
} else {
cmd->cmd_func = mm_clear_drive_cmd_func;
}
cmd->cmd_name = strdup("clear drive");
cmd->cmd_mount_info.cmi_drive = strdup(drive_name);
cmd->cmd_mount_info.cmi_library = strdup(PQgetvalue(lm_name, 0, 1));
/* Force or not */
cmd->cmd_mount_info.cui_force = force;
/* Cart_pcl */
if (cart_pcl != NULL) {
mm_set_mount_info_pcl(cart_pcl,
&cmd->cmd_mount_info);
}
pthread_mutex_lock(&mm_data->mm_queue_mutex);
mms_list_insert_tail(&mm_data->mm_cmd_queue, cmd);
pthread_mutex_unlock(&mm_data->mm_queue_mutex);
mm_clear_db(&lm_name);
return (cmd);
}