mm_mmp_mount.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 <pthread.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 "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_task.h"
#include "mm_path.h"
static char *_SrcFile = __FILE__;
#define SELECT_GETALL "select \"DriveName\" from " \
"getall('%s', '%s', '%s');"
#define SELECT_LIB "select \"LibraryName\" from " \
"gettypename('%s', '%s');"
/* Unmount command states */
#define UM_CANDIDATE_SELECTION 0
#define UM_DM_DETACH 1
#define UM_SCHEDULE_UNLOAD 2
#define UM_DM_UNLOAD 3
#define UM_DM_RELEASE 4
#define UM_LM_UNMOUNT 5
#define UM_FINAL 100
extern int mm_get_dest(mm_wka_t *mm_wka, mm_command_t *cmd);
extern int mm_get_source(mm_wka_t *mm_wka, mm_command_t *cmd);
extern int mm_get_const(mm_wka_t *mm_wka, mm_command_t *cmd);
extern int mm_add_match_list(char *str, mms_list_t *list);
extern void tm_be_cancel_all(mm_command_t *cmd);
void
mm_print_unmount_state(int state) {
switch (state) {
case UM_CANDIDATE_SELECTION:
mms_trace(MMS_DEBUG,
"unmount candidate selection");
return;
case UM_DM_DETACH:
mms_trace(MMS_DEBUG,
"add dm detach command");
return;
case UM_SCHEDULE_UNLOAD:
mms_trace(MMS_DEBUG,
"schedule dm unload command");
return;
case UM_DM_UNLOAD:
mms_trace(MMS_DEBUG,
"add dm unload command");
return;
case UM_DM_RELEASE:
mms_trace(MMS_DEBUG,
"add dm release command");
return;
case UM_LM_UNMOUNT:
mms_trace(MMS_DEBUG,
"add lm unmount command");
return;
case UM_FINAL:
mms_trace(MMS_DEBUG,
"umount final commmand state");
return;
}
}
void
mm_print_mount_candidates(mm_command_t *cmd) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
cmi_cart_list_t *cart = NULL;
cmi_drive_list_t *drive = NULL;
mms_trace(MMS_INFO, "Candidate Cartridges are :");
mms_list_foreach(&mount_info->cmi_cart_list, cart) {
if (cart->cmi_cart_not_ready) {
mms_trace(MMS_INFO, " Cartridge, %s, (not ready)",
cart->cmi_cart_id);
} else {
mms_trace(MMS_INFO, " Cartridge, %s",
cart->cmi_cart_id);
}
if (cart->cmi_cart_pcl != NULL) {
mms_trace(MMS_INFO, " %s",
cart->cmi_cart_pcl);
}
mms_trace(MMS_INFO, " Library, %s",
cart->cmi_library);
mms_trace(MMS_INFO,
" Drive Candidates:");
mms_list_foreach(&cart->cmi_drive_list, drive) {
if (drive->cmi_mode_valid == 0) {
mms_trace(MMS_INFO, " %s"
" * no DM configured *",
drive->cmi_drive_name);
} else {
if (drive->cmi_drive_not_ready) {
mms_trace(MMS_INFO,
" %s, (not ready)",
drive->cmi_drive_name);
} else {
mms_trace(MMS_INFO, " %s",
drive->cmi_drive_name);
}
}
}
}
}
void
mm_print_accessmodes(mm_command_t *cmd) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
cmi_mode_list_t *mode = NULL;
int i;
mms_trace(MMS_INFO, "Number of First Mount Tokens's is %d",
mount_info->cmi_num_firstmount);
for (i = 0; i < mount_info->cmi_num_firstmount; i ++) {
mms_trace(MMS_INFO, " First Mount Token %d is %s", i,
mount_info->cmi_firstmount[i]);
}
mms_trace(MMS_INFO, "Total Number of Access Modes is %d",
mount_info->cmi_total_modes);
mms_list_foreach(&mount_info->cmi_mode_list, mode) {
for (i = 0;
i < mode->cmi_num_accessmode;
i ++) {
mms_trace(MMS_INFO, " Mode Token %d is %s", i,
mode->cmi_accessmode[i]);
}
}
}
void
mm_print_mount_summary(mm_wka_t *mm_wka, mm_command_t *cmd) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
cci_t *conn = &mm_wka->wka_conn;
/* Print mount information */
if (mount_info->cmi_operation == MM_MOUNT) {
mms_trace(MMS_INFO, "*** Mount Summary ***");
} else {
mms_trace(MMS_INFO, "*** UnMount Summary ***");
}
mms_trace(MMS_INFO, "Application is %s",
conn->cci_client);
mms_trace(MMS_INFO, "Instance is %s",
conn->cci_instance);
if (cmd->wka_ptr->wka_privilege == MM_PRIV_STANDARD) {
mms_trace(MMS_INFO,
"Standard Privilege");
} else {
mms_trace(MMS_INFO,
"Privileged Client");
}
switch (mount_info->cmi_type) {
case MM_SIDE:
mms_trace(MMS_INFO, " Type is SIDE");
break;
case MM_PARTITION:
mms_trace(MMS_INFO, " Type is PARTITION");
break;
case MM_VOLUME:
mms_trace(MMS_INFO, " Type is VOLUME");
break;
}
switch (mount_info->cmi_when) {
case MM_BLOCKING:
mms_trace(MMS_INFO, " When is 'blocking'");
break;
case MM_IMMEDIATE:
mms_trace(MMS_INFO, " When is 'immediate'");
break;
}
if (mount_info->cmi_where)
mms_trace(MMS_INFO,
" Where is %s", mount_info->cmi_where);
/* Print access modes */
if (mount_info->cmi_operation == MM_MOUNT)
mm_print_accessmodes(cmd);
/* Print all the cartridge/library/drive information */
mm_print_mount_candidates(cmd);
}
int
mm_check_drive(mm_wka_t *mm_wka, mm_command_t *cmd,
cmi_drive_list_t *drive_struct,
char *cart_id, char *dm_name, mm_db_t *db)
{
/* Need to set cmd error buf for every return (0) */
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
cmi_mode_list_t *mode;
char *cap_tokens = NULL;
int a_mode = 0;
char *drive = drive_struct->cmi_drive_name;
/* Check if a DM is configured for this drive */
if (mm_db_exec(HERE, db, "select * from \"DMCAPABILITYGROUP\" "
"where \"DriveName\" = '%s';", drive) != MM_DB_DATA) {
mms_trace(MMS_ERR, "Error getting DMCAPABILITYGROUP");
mm_sql_db_err_rsp_new(cmd, db);
return (0);
}
if (PQntuples(db->mm_db_results) == 0) {
/* DM is not configured for this drive */
mm_response_error(cmd,
ECLASS_CONFIG,
"EDRVNODMCONFIGURED",
5035,
"dm",
dm_name,
"drive",
drive,
MESS_END);
mm_clear_db(&db->mm_db_results);
return (0);
}
mm_clear_db(&db->mm_db_results);
/* Check the cartridge shape */
if (mm_db_exec(HERE, db,
"select distinct * from drive_cart('%s', '%s');",
drive, cart_id) != MM_DB_DATA) {
mms_trace(MMS_ERR, "Error checking drive shape");
mm_sql_db_err_rsp_new(cmd, db);
return (0);
}
if (PQntuples(db->mm_db_results) == 0) {
/* Drive does not support this cartridge shape */
mms_trace(MMS_DEVP, "Drive does not support "\
"this cartridge shape, %s %s", drive, cart_id);
mm_response_error(cmd,
ECLASS_COMPAT,
"ECARTDRVNOTCOMPATIBLE",
5096,
"drive",
drive,
"cart",
cart_id,
MESS_END);
mm_clear_db(&db->mm_db_results);
return (0);
}
mm_clear_db(&db->mm_db_results);
/* For each Access Mode, check if the drive supports it */
mms_list_foreach(&mount_info->cmi_mode_list, mode) {
mms_trace(MMS_DEVP,
"checking a mode");
a_mode = 1;
cap_tokens = (char *)mm_check_mode(mm_wka,
cmd, drive, mode,
cart_id, db);
if (cap_tokens != NULL) {
/* There is at least one supported mode */
mms_trace(MMS_DEVP, "Good mode is %s",
cap_tokens);
/* mode is ok */
free(cap_tokens);
return (1);
}
}
if (a_mode) {
/* there was at least 1 mode passed, */
/* and none were not good, return error */
if (cap_tokens != NULL) {
free(cap_tokens);
}
mm_response_error(cmd,
ECLASS_COMPAT,
"ECARTDRVNOTCOMPATIBLE",
5036,
"dm",
dm_name,
"drive",
drive,
MESS_END);
return (0);
}
/* No modes exist, access is default */
if (cap_tokens != NULL) {
free(cap_tokens);
}
return (1);
no_mem:
MM_ABORT_NO_MEM();
return (MM_CMD_ERROR);
}
#ifdef MM_LIBRARY_DRIVE_HAS_PCL
static int
mm_library_drive_has_pcl(mm_command_t *cmd, char *library, char *drive,
char *cart_pcl)
{
mm_db_t *db = &cmd->wka_ptr->mm_data->mm_db;
int loaded;
if (mm_db_exec(HERE, db, "select \"DriveName\" from \"DRIVE\" "
"where \"LibraryName\" = '%s' "
"and \"DriveName\" = '%s' "
"and \"CartridgePCL\" = '%s' "
"and \"DriveLibraryAccessible\" = 'true' "
"and \"DriveLibraryOccupied\" = 'true' "
"and \"DriveBroken\" = 'false' "
"and \"DriveDisabled\" = 'false';",
library, drive, cart_pcl) != MM_DB_DATA) {
return (0);
}
loaded = (PQntuples(db->mm_db_results) != 1 ? 0 : 1);
mm_clear_db(&db->mm_db_results);
return (loaded);
}
#endif
int
mm_candidate_drive_ok(mm_wka_t *mm_wka,
mm_command_t *cmd, mm_db_t *db,
char *candidate_cartid,
cmi_drive_list_t *drive) {
/* Determines if the candidate drive */
/* is available as a candidate */
char *candidate_drive = drive->cmi_drive_name;
char *candidate_dm = drive->cmi_dm_name;
cci_t *conn = &mm_wka->wka_conn;
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
mm_dm_stat_t *dm_stat = NULL;
mm_drive_stat_t *drive_stat = NULL;
int rc;
mms_trace(MMS_DEVP, "mm_candidate_drive_ok");
if ((drive_stat = mm_get_drive_status(candidate_drive, db)) == NULL) {
mms_trace(MMS_ERR,
"Error getting drive information, "
"drive %s",
candidate_drive);
mm_system_error(cmd,
"failed to get drive information");
rc = 0; goto end;
}
/* For mounts we know drive and host, for umounts we know dm */
/* Use the approperate call to getdmstatus */
if (mount_info->cmi_operation == MM_MOUNT) {
if ((dm_stat = mm_get_dm_status(NULL, candidate_drive,
mount_info->cmi_where, db)) == NULL) {
mms_trace(MMS_ERR,
"Error getting dm information, "
"drive %s",
candidate_drive);
mm_system_error(cmd,
"failed to get dm information");
rc = 0; goto end;
}
} else {
mms_trace(MMS_DEVP,
"cmi_dm_name/candidate_dm == %s",
candidate_dm);
if ((dm_stat = mm_get_dm_status(candidate_dm, NULL,
NULL, db)) == NULL) {
mms_trace(MMS_ERR,
"Error getting dm information, "
"drive %s",
candidate_drive);
mm_system_error(cmd,
"failed to get dm information");
rc = 0; goto end;
}
}
mm_print_drive_status(drive_stat);
mm_print_dm_status(dm_stat);
/* The order of check is the order errors get returned */
/* check higher level problems before lower level */
/* ie. online, diabled first */
/* Exclusive access check */
if (strcmp(drive_stat->drive_stat_excl_app, "none") != 0) {
if (strcmp(conn->cci_client,
drive_stat->drive_stat_excl_app) != 0) {
mms_trace(MMS_DEVP,
"%s exclusive app is not clients app,"
" ExclusiveAppName != %s or none",
candidate_drive,
conn->cci_client);
mm_response_error(cmd,
ECLASS_EXPLICIT,
"EAPPDRVNOACC",
5027,
"app", conn->cci_client,
"drive", candidate_drive,
MESS_END);
rc = 0; goto end;
}
}
/* DRIVEGROUPAPPLICATION check */
if (cmd->wka_ptr->wka_privilege == MM_PRIV_STANDARD) {
mms_trace(MMS_DEVP,
"Non-privileged client, "
"checking Drive Access");
/* standard priv, check drive group access */
if (mm_db_exec(HERE, db,
"select \"DRIVEGROUPAPPLICATION\".\"ApplicationName\" "
"from \"DRIVEGROUPAPPLICATION\" "
"where \"DriveGroupName\" = '%s' and "
"\"ApplicationName\" = '%s';",
drive_stat->drive_stat_group,
conn->cci_client) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"Error getting drive group information, "
"drive %s, db trans failed",
candidate_drive);
mm_sql_db_err_rsp_new(cmd, db);
rc = 0; goto end;
}
if (PQntuples(db->mm_db_results) == 0) {
mms_trace(MMS_DEVP,
"%s does not have "
"access to drive group %s",
conn->cci_client,
drive_stat->drive_stat_group);
mm_response_error(cmd,
ECLASS_EXPLICIT,
"EAPPDRVNOACC",
5030,
"app", conn->cci_client,
"drive", candidate_drive,
MESS_END);
mm_clear_db(&db->mm_db_results);
rc = 0; goto end;
}
mm_clear_db(&db->mm_db_results);
} else {
mms_trace(MMS_DEVP,
"Privileged Client, "
"skip Drive Access check");
}
/* Online check */
if ((strcmp(drive_stat->drive_stat_online, "false") == 0) ||
(strcmp(drive_stat->drive_stat_online, "f") == 0)) {
mms_trace(MMS_DEVP,
"%s is not online",
candidate_drive);
mm_response_error(cmd,
ECLASS_PERMPRIV,
"EDRIVEOFFLINE",
5029,
"drive", candidate_drive,
MESS_END);
rc = 0; goto end;
}
/* Drive In use */
if ((mount_info->cmi_operation == MM_MOUNT) &&
(strcmp(drive_stat->drive_stat_soft, "ready") != 0)) {
mms_trace(MMS_DEVP,
"%s is not ready,"
" DriveStateSoft != ready ",
candidate_drive);
drive->cmi_drive_not_ready = 1;
if (mount_info->cmi_when == MM_IMMEDIATE) {
mm_response_error(cmd,
ECLASS_RETRY,
"EDRVINUSE",
5025,
"drive", candidate_drive,
MESS_END);
rc = 0; goto end;
} else {
mms_trace(MMS_DEVP,
"drive in use, keep as"
" candidate for blocking mounts");
}
/* Keep this drive as a candidate for blocking mounts */
}
if ((mount_info->cmi_operation == MM_MOUNT) &&
((strcmp(drive_stat->drive_stat_hard, "loaded") == 0) ||
(strcmp(drive_stat->drive_stat_drvlib_occ, "true") == 0) ||
(strcmp(drive_stat->drive_stat_drvlib_occ, "t") == 0))) {
/* Find this drive's delayed unload and set to dispatch */
mms_trace(MMS_DEVP,
"drive is loaded with %s, need to unload",
drive_stat->drive_stat_pcl);
if ((strcmp(drive_stat->drive_stat_hard, "unloading") == 0) ||
(strcmp(drive_stat->drive_stat_hard, "loading") == 0)) {
/* This drive is in the process of unloading */
mms_trace(MMS_DEVP,
"This drive is in the process of "
"unloading/loading");
drive->cmi_drive_not_ready = 1;
if (mount_info->cmi_when == MM_IMMEDIATE) {
/* make a real error message for this */
mm_response_error(cmd,
ECLASS_RETRY,
"EDRVUNLOADING",
5102,
"drive", candidate_drive,
MESS_END);
rc = 0; goto end;
}
} else {
drive->cmi_drive_loaded = 1;
drive->cmi_loaded_pcl = NULL;
drive->cmi_loaded_pcl = mms_strapp(drive->
cmi_loaded_pcl,
drive_stat->drive_stat_pcl);
if (strcmp(MM_NON_MMS_CART,
drive_stat->drive_stat_pcl) == 0) {
drive->cmi_drive_not_ready = 1;
mms_trace(MMS_DEVP,
"drive is loaded with a non-mms tape");
if (mount_info->cmi_when == MM_IMMEDIATE) {
mm_response_error(cmd,
ECLASS_RETRY,
"EDRVINUSE",
5028,
"drive", candidate_drive,
MESS_END);
rc = 0; goto end;
}
}
}
}
if (mount_info->cmi_operation == MM_UNMOUNT) {
if ((strcmp(drive_stat->drive_stat_hard, "loaded") != 0) ||
(strcmp(drive_stat->drive_stat_drvlib_occ, "t") != 0)) {
mms_trace(MMS_DEVP,
"%s not loaded/occupied with tape, "
"but has MOUNTPHYSICAL",
candidate_drive);
mm_system_error(cmd,
"drive with MOUNTPHYSICAL not "
"loaded/occupied with tape");
rc = 0; goto end;
}
}
/* Drive disabled */
if ((strcmp(drive_stat->drive_stat_disabled, "true") == 0) ||
(strcmp(drive_stat->drive_stat_disabled, "t") == 0)) {
mms_trace(MMS_DEVP,
"%s is disabled",
candidate_drive);
if (strcmp(drive_stat->drive_stat_disabled,
"temporary") == 0) {
mm_response_error(cmd,
ECLASS_PERMPRIV,
"EDRVDISABLEDTEMP",
5022,
"drive", candidate_drive,
MESS_END);
} else {
mm_response_error(cmd,
ECLASS_PERMPRIV,
"EDRVDISABLEDPERM",
5023,
"drive", candidate_drive,
MESS_END);
}
rc = 0; goto end;
}
/* Drive Broken */
if ((strcmp(drive_stat->drive_stat_broken, "true") == 0) ||
(strcmp(drive_stat->drive_stat_broken, "t") == 0)) {
mms_trace(MMS_DEVP,
"%s is broken",
candidate_drive);
mm_response_error(cmd,
ECLASS_CONFIG,
"EDRVBROKEN",
5024,
"drive", candidate_drive,
MESS_END);
rc = 0; goto end;
}
/* Drive is library accessible */
if ((strcmp(drive_stat->drive_stat_lib_acc, "false") == 0) ||
(strcmp(drive_stat->drive_stat_lib_acc, "f") == 0)) {
mms_trace(MMS_DEVP,
"%s is not accessible",
candidate_drive);
mm_response_error(cmd,
ECLASS_INTERNAL,
"ELMDRVNOTACCESS",
5026,
"drive", candidate_drive,
MESS_END);
rc = 0; goto end;
}
/* DM Status Checks */
if (strcmp(dm_stat->dm_stat_soft, "ready") != 0) {
mms_trace(MMS_DEVP,
"DM for %s is not ready,"
" DMStateSoft != ready ",
candidate_drive);
if (strcmp(dm_stat->dm_stat_soft,
"absent") == 0) {
mm_response_error(cmd,
ECLASS_RETRY,
"EDMNOTCONNECTED",
5032,
"dm",
dm_stat->dm_stat_name,
"drive",
candidate_drive,
MESS_END);
rc = 0; goto end;
} else if (strcmp(dm_stat->dm_stat_soft,
"disconnected") == 0) {
mm_response_error(cmd,
ECLASS_CONFIG,
"EDRVBROKEN",
5033,
"dm",
dm_stat->dm_stat_name,
"drive",
candidate_drive,
MESS_END);
rc = 0; goto end;
} else if (strcmp(dm_stat->dm_stat_soft,
"not ready") == 0) {
/* drive is not ready for blocked */
drive->cmi_drive_not_ready = 1;
if (mount_info->cmi_when == MM_IMMEDIATE) {
mm_response_error(cmd,
ECLASS_RETRY,
"EDMSTILLBOOTING",
5034,
"dm",
dm_stat->dm_stat_name,
"drive",
candidate_drive,
MESS_END);
rc = 0; goto end;
}
} else if (strcmp(dm_stat->dm_stat_soft,
"present") == 0) {
/* drive is not ready for blocked */
drive->cmi_drive_not_ready = 1;
if (mount_info->cmi_when == MM_IMMEDIATE) {
mm_response_error(cmd,
ECLASS_CONFIG,
"EDRVNODMCONFIGURED",
5034,
"dm",
dm_stat->dm_stat_name,
"drive",
candidate_drive,
MESS_END);
rc = 0; goto end;
}
} else if ((mount_info->cmi_operation == MM_MOUNT) &&
(strcmp(dm_stat->dm_stat_soft,
"reserved") == 0)) {
/* drive is not ready for blocked */
drive->cmi_drive_not_ready = 1;
if (mount_info->cmi_when == MM_IMMEDIATE) {
mm_response_error(cmd,
ECLASS_RETRY,
"EDRVINUSE",
5098,
"dm",
dm_stat->dm_stat_name,
MESS_END);
rc = 0; goto end;
}
}
} else if (mount_info->cmi_operation == MM_UNMOUNT) {
/* Unmount, and DM is ready */
mms_trace(MMS_DEVP,
"%s is in incorrect state for unmount",
dm_stat->dm_stat_name);
mm_system_error(cmd,
"DM is in incorrect state for unmount");
rc = 0; goto end;
}
if (strcmp(dm_stat->dm_stat_hard, "ready") != 0) {
mms_trace(MMS_DEVP,
"DM for %s is not ready,"
" DMStateHard != ready ",
candidate_drive);
mm_response_error(cmd,
ECLASS_CONFIG,
"EDRVBROKEN",
5031,
"drive",
candidate_drive,
"dm",
dm_stat->dm_stat_name,
MESS_END);
rc = 0; goto end;
}
if (mount_info->cmi_operation == MM_UNMOUNT) {
mms_trace(MMS_DEVP,
"Drive/DM Status ok for unmounts");
rc = 1; goto end;
}
mms_trace(MMS_DEVP,
"DM Status ok, check DM accessmodes DM, %s",
dm_stat->dm_stat_name);
if (mm_check_drive(mm_wka, cmd,
drive,
candidate_cartid,
dm_stat->dm_stat_name,
db) == 1) {
/* DM supports the access modes */
mms_trace(MMS_DEVP,
"DM configured for at least 1 access mode");
} else {
mms_trace(MMS_DEVP,
"DM not configured to support the access mode");
/* Error buf should be set by check drive */
rc = 0; goto end;
}
rc = 1; goto end;
end:
mm_free_drive_status(drive_stat);
mm_free_dm_status(dm_stat);
return (rc);
}
int
mm_candidate_cartridge_ok(mm_wka_t *mm_wka,
mm_command_t *cmd, mm_db_t *db,
cmi_cart_list_t *cart_struct) {
uuid_text_t *candidate_cartid = &cart_struct->cmi_cart_id;
cci_t *conn = &mm_wka->wka_conn;
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
PGresult *cart = NULL;
PGresult *volume = NULL;
PGresult *slot = NULL;
int rc;
mms_trace(MMS_DEVP, "mm_candidate_cartridge_ok");
if (mm_db_exec(HERE, db,
"select "
"\"CARTRIDGE\".\"CartridgeState\", "
"\"CARTRIDGE\".\"CartridgeStatus\", "
"\"CARTRIDGE\".\"CartridgeGroupName\", "
"\"CARTRIDGE\".\"CartridgeDriveOccupied\" "
"from \"CARTRIDGE\" "
"where \"CartridgeID\" = '%s';",
candidate_cartid) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"Error getting cartridge information, "
"cartridge, %s, db trans failed",
candidate_cartid);
mm_sql_db_err_rsp_new(cmd, db);
rc = 0; goto end;
}
cart = db->mm_db_results;
if (PQntuples(cart) != 1) {
mms_trace(MMS_ERR,
"Error getting cartridge information, "
"cartridge, %s, db results != 1",
candidate_cartid);
mm_system_error(cmd,
"row number mismatch getting "
"cartridge information");
rc = 0; goto end;
}
mms_trace(MMS_DEVP,
"Cartridge Status for Cartridge, %s",
candidate_cartid);
mms_trace(MMS_DEVP,
" CartridgeState = %s",
PQgetvalue(cart, 0, 0));
mms_trace(MMS_DEVP,
" CartridgeStatus = %s",
PQgetvalue(cart, 0, 1));
mms_trace(MMS_DEVP,
" CartridgeGroup = %s",
PQgetvalue(cart, 0, 2));
mms_trace(MMS_DEVP,
" CartridgeDriveOccupied = %s",
PQgetvalue(cart, 0, 3));
/* Ignore this attribute for now */
/*
* if (strcmp(PQgetvalue(cart, 0, 0), "defined") != 0) {
*
* }
*/
if ((mount_info->cmi_operation == MM_MOUNT) &&
(strcmp(PQgetvalue(cart, 0, 1), "available") != 0)) {
mms_trace(MMS_DEVP,
"%s is in use,"
" CartridgeStatus != available ",
candidate_cartid);
if (strcmp(PQgetvalue(cart, 0, 1),
"unavailable") == 0) {
mm_response_error(cmd,
ECLASS_CONFIG,
"ECARTNOTLOCATED",
5037,
"cart",
candidate_cartid,
MESS_END);
rc = 0; goto end;
}
/* mark this cartridge not ready */
/* for blocked mounts */
cart_struct->cmi_cart_not_ready = 1;
if (mount_info->cmi_when == MM_IMMEDIATE) {
/* State is 'in use' */
mm_response_error(cmd,
ECLASS_RETRY,
"ECARTINUSE",
5038,
"cart",
candidate_cartid,
MESS_END);
rc = 0; goto end;
}
}
if ((mount_info->cmi_operation == MM_UNMOUNT) &&
(strcmp(PQgetvalue(cart, 0, 1), "in use") != 0)) {
mms_trace(MMS_DEVP,
"%s is not in use,"
" CartridgeStatus != in use ",
candidate_cartid);
mm_system_error(cmd,
"cartridge status is not in use");
rc = 0; goto end;
}
/* Check if this CARTRIDGE has a SLOT created for it */
if (mm_db_exec(HERE, db,
"select \"SlotName\" "
"from \"SLOT\" "
"where \"CartridgeID\" = '%s';",
candidate_cartid) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"Error getting slot info, "
"cartridge, %s, db trans failed",
candidate_cartid);
mm_sql_db_err_rsp_new(cmd, db);
rc = 0; goto end;
}
slot = db->mm_db_results;
if (PQntuples(slot) == 0) {
mms_trace(MMS_DEVP,
"no slot found for cartridge, %s",
candidate_cartid);
mm_response_error(cmd,
ECLASS_CONFIG,
"ENOSLOT",
5095,
"cart",
candidate_cartid,
MESS_END);
rc = 0; goto end;
}
if (mount_info->cmi_operation == MM_UNMOUNT) {
/* skip volume check */
/* This cart already has mapped to mount physical */
mms_trace(MMS_DEVP,
"skip vol check for unmount");
rc = 1; goto end;
}
/* Get VOLUME information */
mms_trace(MMS_DEVP,
"Checking for Volumes");
if (mm_db_exec(HERE, db,
"select \"ApplicationName\" "
"from \"VOLUME\" where "
"\"CartridgeID\" = '%s' and "
"\"ApplicationName\" = '%s';",
candidate_cartid,
conn->cci_client) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"Error getting volume information, "
"cartridge, %s, db trans failed",
candidate_cartid);
mm_sql_db_err_rsp_new(cmd, db);
rc = 0; goto end;
}
volume = db->mm_db_results;
if (PQntuples(volume) == 0) {
mms_trace(MMS_DEVP,
"%s doesn't have a volume "
"on cartridge, %s",
conn->cci_client,
candidate_cartid);
mm_response_error(cmd,
ECLASS_CONFIG,
"EAPPHASNOVOLS",
5040,
"app",
conn->cci_client,
"cart",
candidate_cartid,
MESS_END);
rc = 0; goto end;
}
rc = 1; goto end;
end:
if (cart != NULL) {
mm_clear_db(&cart);
}
if (volume != NULL) {
mm_clear_db(&volume);
}
if (slot != NULL) {
mm_clear_db(&slot);
}
return (rc);
}
int
mm_candidate_library_ok(mm_command_t *cmd, mm_db_t *db,
char *candidate_library) {
/* Determines if the candidate library */
/* is available as a candidate */
mm_lm_stat_t *lm_stat = NULL;
mm_lib_stat_t *lib_stat = NULL;
int rc;
mms_trace(MMS_DEVP, "mm_candidate_library_ok");
if ((lib_stat = mm_get_library_status(candidate_library, db)) == NULL) {
mms_trace(MMS_ERR,
"Error getting library information, "
"library %s",
candidate_library);
mm_system_error(cmd,
"failed to get library "
"information from database");
rc = 0; goto end;
}
mm_print_library_status(lib_stat);
if ((strcmp(lib_stat->lib_stat_online, "false") == 0) ||
(strcmp(lib_stat->lib_stat_online, "f") == 0)) {
mms_trace(MMS_DEVP,
"%s is not online",
candidate_library);
mm_response_error(cmd,
ECLASS_PERMPRIV,
"ELIBRARYOFFLINE",
5041,
"lib",
candidate_library,
MESS_END);
rc = 0; goto end;
}
if ((strcmp(lib_stat->lib_stat_disabled, "true") == 0) ||
(strcmp(lib_stat->lib_stat_disabled, "t") == 0)) {
mms_trace(MMS_DEVP,
"%s is disabled",
candidate_library);
if (strcmp(lib_stat->lib_stat_disabled,
"temporary") == 0) {
mm_response_error(cmd,
ECLASS_PERMPRIV,
"ELIBDISABLEDTEMP",
5042,
"lib",
candidate_library,
MESS_END);
} else {
mm_response_error(cmd,
ECLASS_PERMPRIV,
"ELIBDISABLEDPERM",
5043,
"lib",
candidate_library,
MESS_END);
}
rc = 0; goto end;
}
if ((strcmp(lib_stat->lib_stat_broken, "true") == 0) ||
(strcmp(lib_stat->lib_stat_broken, "t") == 0)) {
mms_trace(MMS_DEVP,
"%s is broken",
candidate_library);
mm_response_error(cmd,
ECLASS_CONFIG,
"ELIBBROKEN",
5044,
"lib",
candidate_library,
MESS_END);
rc = 0; goto end;
}
mms_trace(MMS_DEVP,
"Library status ok, check LM");
/* Library is online and ready, get LM status */
if ((lm_stat = mm_get_lm_status(lib_stat->lib_stat_lm,
db)) == NULL) {
mms_trace(MMS_ERR,
"Error getting lm information, "
"library %s",
candidate_library);
mm_system_error(cmd,
"failed to get lm information");
rc = 0; goto end;
}
mm_print_lm_status(lm_stat);
if (strcmp(lm_stat->lm_stat_hard, "ready") != 0) {
mms_trace(MMS_DEVP,
"%s is not ready,"
" LMStateHard != ready ",
lib_stat->lib_stat_lm);
mm_response_error(cmd,
ECLASS_CONFIG,
"ELIBBROKEN",
5045,
"lm",
lib_stat->lib_stat_lm,
MESS_END);
rc = 0; goto end;
}
if (strcmp(lm_stat->lm_stat_soft, "ready") != 0) {
mms_trace(MMS_DEVP,
"%s is not ready,"
" LMStateSoft != ready ",
lib_stat->lib_stat_lm);
if (strcmp(lm_stat->lm_stat_soft,
"absent") == 0) {
mm_response_error(cmd,
ECLASS_RETRY,
"ELMNOTCONNECTED",
5046,
"lm",
lib_stat->lib_stat_lm,
"lib",
lib_stat->lib_stat_name,
MESS_END);
}
if (strcmp(lm_stat->lm_stat_soft,
"present") == 0) {
mm_response_error(cmd,
ECLASS_RETRY,
"ELMNOTREADY",
5047,
"lm",
lib_stat->lib_stat_lm,
"lib",
lib_stat->lib_stat_name,
MESS_END);
}
if (strcmp(lm_stat->lm_stat_soft,
"disconnected") == 0) {
mm_response_error(cmd,
ECLASS_CONFIG,
"ELIBBROKEN",
5048,
"lm",
lib_stat->lib_stat_lm,
"lib",
lib_stat->lib_stat_name,
MESS_END);
}
if (strcmp(lm_stat->lm_stat_soft,
"not ready") == 0) {
mm_response_error(cmd,
ECLASS_RETRY,
"ELMSTILLBOOTING",
5049,
"lm",
lib_stat->lib_stat_lm,
"lib",
lib_stat->lib_stat_name,
MESS_END);
}
rc = 0; goto end;
}
mms_trace(MMS_DEVP,
"LM status ok");
rc = 1; goto end;
end:
mm_free_library_status(lib_stat);
mm_free_lm_status(lm_stat);
return (rc);
}
int
mm_insert_next_drive(mms_list_t *drive_list, cmi_drive_list_t *drive_struct) {
/*
* This will insert the drive_struct into its
* proper place in drive_list
*
* the drives are inserted in order of drive_priority
* check the dm shape and dm density priority to
* arrange the drives within each drive priority group
*/
cmi_drive_list_t *drive;
cmi_drive_list_t *next_drive;
int drv_priority;
int dm_shape_priority;
int dm_density_priority;
int cur_drv_priority;
int cur_shape_priority;
int cur_density_priority;
int next_drv_priority;
int a_drive = 0;
drv_priority = drive_struct->cmi_drv_priority;
dm_shape_priority = drive_struct->cmi_dm_shape_priority;
dm_density_priority = drive_struct->cmi_dm_density_priority;
for (drive = mms_list_head(drive_list);
drive != NULL;
drive = next_drive) {
a_drive = 1;
next_drive =
mms_list_next(drive_list,
drive);
cur_drv_priority = drive->cmi_drv_priority;
cur_shape_priority = drive->cmi_dm_shape_priority;
cur_density_priority = drive->cmi_dm_density_priority;
if (cur_drv_priority != drv_priority) {
/* go to the next drive */
continue;
}
if (cur_shape_priority > dm_shape_priority) {
/* Insert before cur */
mms_list_insert_before(drive_list, drive, drive_struct);
return (0);
}
if ((cur_shape_priority == dm_shape_priority) &&
(cur_density_priority > dm_density_priority)) {
/* Insert before cur */
mms_list_insert_before(drive_list, drive, drive_struct);
return (0);
}
if (next_drive == NULL) {
mms_list_insert_after(drive_list, drive, drive_struct);
return (0);
}
next_drv_priority = next_drive->cmi_drv_priority;
if (next_drv_priority != drv_priority) {
mms_list_insert_after(drive_list, drive, drive_struct);
return (0);
}
}
mms_list_insert_tail(drive_list,
drive_struct);
return (a_drive);
}
cmi_drive_list_t *
mm_setup_drive_unmount(mm_command_t *cmd,
mm_db_t *db,
cmi_cart_list_t *cart,
PGresult *drive_results,
int drive_row) {
cmi_drive_list_t *drive = NULL;
PGresult *dm;
char *dm_name = NULL;
char *candidate_drive = PQgetvalue(drive_results, drive_row, 0);
mms_trace(MMS_DEVP, "mm_setup_drive_unmount");
if (mm_db_exec(HERE, db,
"select \"DMName\""
" from \"DRIVE\" where "
"\"DriveName\" = '%s';",
candidate_drive) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"Error getting dm information");
mm_sql_db_err_rsp_new(cmd, db);
return (NULL);
}
if (PQntuples(db->mm_db_results) == 0) {
mms_trace(MMS_ERR,
"Coudn't find DRIVE for "
"this drive, %s",
candidate_drive);
mm_system_error(cmd,
"missing DRIVE obj during unmount");
mm_clear_db(&db->mm_db_results);
return (NULL);
}
dm = db->mm_db_results;
dm_name = PQgetvalue(dm, 0, 0);
drive = NULL;
drive = (cmi_drive_list_t *)
calloc(1,
sizeof (cmi_drive_list_t));
if (drive == NULL) {
mms_trace(MMS_ERR,
"Unable to malloc"\
" cmi_drive_list: %s",
strerror(errno));
mm_system_error(cmd,
"unable to allocate mem for drive stat");
mm_clear_db(&dm);
return (NULL);
}
drive->cmi_drive_name =
strdup(candidate_drive);
drive->cmi_mode_valid = 1;
drive->cmi_drive_not_ready = 0;
drive->cmi_dm_name = mms_strapp(drive->cmi_dm_name, dm_name);
drive->cmi_dm_shape_priority = 0;
drive->cmi_dm_density_priority = 0;
/* Column references must match what is in mm_mount_init_candidates */
drive->cmi_drv_priority = atoi(PQgetvalue(drive_results,
drive_row, 2));
drive->cmi_drv_num_mounts = atoi(PQgetvalue(drive_results,
drive_row, 3));
mms_list_insert_tail(&cart->cmi_drive_list,
drive);
mm_clear_db(&dm);
return (drive);
}
cmi_drive_list_t *
mm_setup_drive(mm_command_t *cmd,
mm_db_t *db,
cmi_cart_list_t *cart,
PGresult *drive_results,
int drive_row) {
/* drive_results is created in mm_init_candidates */
cmi_drive_list_t *drive = NULL;
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
PGresult *dm_shape;
int dm_shape_priority;
int dm_density_priority;
PGresult *dm;
char *dm_name = NULL;
char *cart_type = cart->cmi_cart_type;
char *bit_format = cart->cmi_bit_format;
int drive_not_ready;
int i;
char *candidate_cartid = cart->cmi_cart_id;
char *candidate_drive = PQgetvalue(drive_results,
drive_row, 0);
char *cur_dm_shape;
char *cur_dm_shape_priority;
char *cur_dm_density;
char *cur_dm_density_priority;
/* get the dm name */
/* get name by host */
if (mm_db_exec(HERE, db,
"select \"DMName\""
" from \"DM\" where "
"\"DriveName\" = '%s' "
"and pg_host_ident("
"\"DMTargetHost\") "
"= pg_host_ident('%s');",
candidate_drive,
mount_info->cmi_where) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"Error getting dm information");
mm_sql_db_err_rsp_new(cmd, db);
return (NULL);
}
if (PQntuples(db->mm_db_results) == 0) {
mms_trace(MMS_ERR,
"No dm configured for "
"this drive, on host %s",
mount_info->cmi_where);
mm_response_error(cmd,
ECLASS_COMPAT,
"EAPPDMDIFFHOSTS",
5050,
"host",
mount_info->cmi_where,
MESS_END);
mm_clear_db(&db->mm_db_results);
return (NULL);
}
dm = db->mm_db_results;
dm_name = PQgetvalue(dm, 0, 0);
/* Check the cartridge shape */
if (mm_db_exec(HERE, db,
"select \"DMSHAPEPRIORITY\".\"DMName\", "
"\"DMSHAPEPRIORITY\".\"DMShapeName\","
"\"DMSHAPEPRIORITY\".\"DMShapePriority\","
"\"DMDENSITYPRIORITY\".\"DMDensityName\","
"\"DMDENSITYPRIORITY\".\"DMDensityPriority\" from "
"\"DMSHAPEPRIORITY\",\"DMDENSITYPRIORITY\""
"where "
"\"DMSHAPEPRIORITY\".\"DMName\" = '%s' and "
"\"DMDENSITYPRIORITY\".\"DMName\" = '%s';",
dm_name,
dm_name) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"Error checking cartridge shape");
mm_sql_db_err_rsp_new(cmd, db);
mm_clear_db(&dm);
return (NULL);
}
drive_not_ready = 0;
if (PQntuples(db->mm_db_results) == 0) {
/* This will be an error for immediate mounts */
/* for blocking keep drive, and set drive_not_ready */
mms_trace(MMS_ERR,
"dm has not been configured for this drive");
drive_not_ready = 1;
}
dm_shape = db->mm_db_results;
dm_shape_priority = -1;
/* Default density is 1 */
dm_density_priority = 1;
for (i = 0; i < PQntuples(dm_shape); i++) {
cur_dm_shape = PQgetvalue(dm_shape, i, 1);
cur_dm_shape_priority = PQgetvalue(dm_shape, i, 2);
cur_dm_density = PQgetvalue(dm_shape, i, 3);
cur_dm_density_priority = PQgetvalue(dm_shape, i, 4);
if (strcmp(cart_type, cur_dm_shape) == 0) {
dm_shape_priority = atoi(cur_dm_shape_priority);
}
if (strcmp(bit_format, cur_dm_density) == 0) {
dm_density_priority = atoi(cur_dm_density_priority);
}
}
if ((dm_shape_priority == -1) &&
(drive_not_ready != 1)) {
/* Drive has configed dm, but slot does not match */
/* Didn't find this dm_shape */
mms_trace(MMS_ERR,
"dm is not configured for this slot type");
mm_response_error(cmd,
ECLASS_COMPAT,
"ECARTDRVSLOTMISMATCH",
5097,
MESS_END);
mm_clear_db(&dm);
mm_clear_db(&dm_shape);
return (NULL);
}
mm_clear_db(&dm_shape);
/* Confirm DM MOUNT POINT */
if (drive_not_ready == 0) {
mms_trace(MMS_DEVP,
"drive is configured, quickly check the mountpoint");
if (mm_db_exec(HERE, db,
"select \"DMName\" from \"DMMOUNTPOINT\" "
"cross join \"CARTRIDGE\" where "
"\"CARTRIDGE\".\"CartridgeMountPoint\" = "
"\"DMMOUNTPOINT\".\"DMMountPoint\""
"and"
"\"CARTRIDGE\".\"CartridgeID\" = '%s'"
"and \"DMMOUNTPOINT\".\"DMName\" = '%s'",
candidate_cartid,
dm_name) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"Error checking cartridge shape");
mm_sql_db_err_rsp_new(cmd, db);
mm_clear_db(&dm);
return (NULL);
}
if (PQntuples(db->mm_db_results) == 0) {
/* This will be an error for immediate mounts */
/* for blocking keep drive, and set drive_not_ready */
mms_trace(MMS_ERR,
"dm does not support this mount point");
mm_response_error(cmd,
ECLASS_COMPAT,
"EDMNOMOUNTPOINT",
5103,
"dm",
dm_name,
MESS_END);
mm_clear_db(&dm);
mm_clear_db(&db->mm_db_results);
return (NULL);
}
mms_trace(MMS_DEVP,
"dm is configured for this cart's mountpoint");
mm_clear_db(&db->mm_db_results);
} else {
mms_trace(MMS_DEVP,
"drive not ready, skip mountpoint check for now");
}
drive = NULL;
drive = (cmi_drive_list_t *)
calloc(1,
sizeof (cmi_drive_list_t));
if (drive == NULL) {
mms_trace(MMS_ERR,
"Unable to malloc"\
" cmi_drive_list: %s",
strerror(errno));
mm_system_error(cmd,
"unable to allocate mem for drive stat");
mm_clear_db(&dm);
return (NULL);
}
drive->cmi_drive_name =
strdup(candidate_drive);
drive->cmi_mode_valid = 1;
drive->cmi_drive_not_ready = drive_not_ready;
drive->cmi_dm_name =
strdup(PQgetvalue(dm,
0, 0));
drive->cmi_dm_shape_priority = dm_shape_priority;
drive->cmi_dm_density_priority = dm_density_priority;
/* Column references must match what is in mm_mount_init_candidates */
drive->cmi_drv_priority = atoi(PQgetvalue(drive_results,
drive_row, 2));
drive->cmi_drv_num_mounts = atoi(PQgetvalue(drive_results,
drive_row, 3));
/* Insert Drives into the correct place in the list here */
/* Drives are already orderd by priority and number mounts */
/* Enforce shape and density priority here */
/* Go down the drive list and find where this */
/* drive's pritoriy group starts */
/* Then insert the current drive according to dm_shape_priority */
/* Maintain the original ordering within like prioritys */
if (mm_insert_next_drive(&cart->cmi_drive_list,
drive)) {
mms_trace(MMS_ERR,
"error inserting drive into list");
mm_free_cmi_drive(drive);
drive = NULL;
}
mm_clear_db(&dm);
return (drive);
}
cmi_cart_list_t *
mm_setup_cart(mm_command_t *cmd,
mm_db_t *db,
PGresult *cart_results,
int row_number) {
cmi_cart_list_t *cart = NULL;
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
/* Column references must match what is in mm_mount_cart_results */
char *candidate_cartid = PQgetvalue(cart_results, row_number, 0);
char *candidate_library = PQgetvalue(cart_results, row_number, 1);
char *candidate_priority = PQgetvalue(cart_results, row_number, 2);
char *candidate_num_mounts = PQgetvalue(cart_results, row_number, 3);
char *cart_type = PQgetvalue(cart_results, row_number, 4);
char *cart_pcl = PQgetvalue(cart_results, row_number, 5);
char *cart_loaded = PQgetvalue(cart_results, row_number, 6);
PGresult *partition_results;
char *bit_format = NULL;
/* Get PARTITION."PartitionBitFormat" */
if (mm_db_exec(HERE, db,
"select \"PARTITION\".\"PartitionBitFormat\" "
"from \"PARTITION\" where \"CartridgeID\" = '%s';",
candidate_cartid) != MM_DB_DATA) {
mm_sql_db_err_rsp_new(cmd, db);
mms_trace(MMS_ERR,
"db error getting PartitionBitFormat");
return (NULL);
}
partition_results = db->mm_db_results;
if (PQntuples(partition_results) == 0) {
mms_trace(MMS_ERR,
"couldn't find PARTITION for %s",
candidate_cartid);
mm_system_error(cmd,
"couldn't find PARTITION");
mm_clear_db(&partition_results);
return (NULL);
}
bit_format = PQgetvalue(db->mm_db_results, 0, 0);
cart = (cmi_cart_list_t *)
calloc(1, sizeof (cmi_cart_list_t));
if (cart == NULL) {
mms_trace(MMS_ERR,
"Unable to malloc cmi_cart_list: %s",
strerror(errno));
mm_system_error(cmd,
"unable to allocate mem for drive list");
mm_clear_db(&partition_results);
return (NULL);
}
mms_list_create(&cart->cmi_drive_list,
sizeof (cmi_drive_list_t),
offsetof(cmi_drive_list_t,
cmi_drive_next));
strcpy(cart->cmi_cart_id, candidate_cartid);
cart->cmi_library = NULL;
cart->cmi_library = mms_strapp(cart->cmi_library,
candidate_library);
cart->cmi_cart_pcl = mms_strapp(cart->cmi_cart_pcl,
cart_pcl);
cart->cmi_cart_type = mms_strapp(cart->cmi_cart_type,
cart_type);
cart->cmi_bit_format = mms_strapp(cart->cmi_bit_format,
bit_format);
cart->cmi_cart_not_ready = 0;
cart->cmi_cart_priority = atoi(candidate_priority);
cart->cmi_cart_num_mounts = atoi(candidate_num_mounts);
if ((strcmp(cart_loaded, "true") == 0) ||
(strcmp(cart_loaded, "t") == 0)) {
cart->cmi_cart_loaded = 1;
} else {
cart->cmi_cart_loaded = 0;
}
mms_list_insert_tail(&mount_info->cmi_cart_list,
cart);
mm_clear_db(&partition_results);
return (cart);
}
int
mm_mount_candidate_loaded(mm_command_t *cmd) {
/*
* this function needs to determine if a candidate
* cartridge is already loaded into a candidate drive.
* If there is, it must set the mount_info
* for the cart/lib/drive/dm
*/
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
cmi_cart_list_t *cart = NULL;
cmi_drive_list_t *drive = NULL;
char *cur_pcl = NULL;
char *cur_cartid = NULL;
char *cur_library = NULL;
char *cur_dm = NULL;
char *cur_drive = NULL;
char *drive_pcl = NULL;
mms_trace(MMS_DEVP,
"mm_mount_candidate_loaded: ");
/* The list should already be ordered */
/* select the 1st available */
mms_list_foreach(&mount_info->cmi_cart_list, cart) {
cur_pcl = cart->cmi_cart_pcl;
cur_library = cart->cmi_library;
cur_cartid = cart->cmi_cart_id;
/* The list should already be ordered */
/* select the 1st available */
if (cart->cmi_cart_not_ready) {
continue;
}
mms_list_foreach(&cart->cmi_drive_list, drive) {
if (drive->cmi_drive_not_ready) {
continue;
}
if (drive->cmi_drive_loaded) {
drive_pcl = drive->cmi_loaded_pcl;
cur_drive = drive->cmi_drive_name;
cur_dm = drive->cmi_dm_name;
if (strcmp(cur_pcl, drive_pcl) == 0) {
/* set this mount info and return */
mm_set_mount_info_cart(cur_cartid,
mount_info);
mm_set_mount_info_drive(cur_drive,
mount_info);
mm_set_mount_info_dm(cur_dm,
mount_info);
mm_set_mount_info_library(cur_library,
mount_info);
mount_info->cmi_mount_cart_loaded = 1;
return (1);
}
}
}
}
return (0);
}
int
mm_mount_open_drive(mm_command_t *cmd) {
/*
* this function needs to determine if there is an
* open drive for a candidate cartridge
* If there is, it must set the mount_info
* for the cart/lib/drive/dm
*/
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
cmi_cart_list_t *cart = NULL;
cmi_drive_list_t *drive = NULL;
char *cur_cartid = NULL;
char *cur_library = NULL;
char *cur_dm = NULL;
char *cur_drive = NULL;
mms_trace(MMS_DEVP,
"mm_mount_open_drive: ");
/* The list should already be ordered */
/* select the 1st available */
mms_list_foreach(&mount_info->cmi_cart_list, cart) {
if (cart->cmi_cart_not_ready) {
continue;
}
cur_library = cart->cmi_library;
cur_cartid = cart->cmi_cart_id;
/* only look at non loaded carts */
if (cart->cmi_cart_loaded) {
continue;
}
/* The list should already be ordered */
/* select the 1st available */
mms_list_foreach(&cart->cmi_drive_list, drive) {
if (drive->cmi_drive_not_ready) {
continue;
}
/* only look at non-loaded drives */
if (drive->cmi_drive_loaded) {
continue;
}
cur_drive = drive->cmi_drive_name;
cur_dm = drive->cmi_dm_name;
/* set this mount info and return */
mm_set_mount_info_cart(cur_cartid,
mount_info);
mm_set_mount_info_drive(cur_drive,
mount_info);
mm_set_mount_info_dm(cur_dm,
mount_info);
mm_set_mount_info_library(cur_library,
mount_info);
return (1);
}
}
return (0);
}
int
mm_unmount_2_drive(mm_command_t *cmd, mm_db_t *db) {
/* check if a loaded candidate cartridge */
/* must be mounted in a drive loaded with a non-candidate */
/* need unmount candidate drive and candidate cart */
/* then mount */
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
cmi_cart_list_t *cart = NULL;
cmi_drive_list_t *drive = NULL;
char *cur_cartid = NULL;
char *cur_pcl = NULL;
char *cur_library = NULL;
char *cur_dm = NULL;
char *cur_drive = NULL;
mms_trace(MMS_DEVP,
"mm_unmount_2_drive: ");
mms_list_foreach(&mount_info->cmi_cart_list, cart) {
if (cart->cmi_cart_not_ready) {
continue;
}
cur_library = cart->cmi_library;
cur_cartid = cart->cmi_cart_id;
cur_pcl = cart->cmi_cart_pcl;
mms_list_foreach(&cart->cmi_drive_list, drive) {
if (drive->cmi_drive_not_ready) {
continue;
}
cur_drive = drive->cmi_drive_name;
cur_dm = drive->cmi_dm_name;
if (cart->cmi_cart_loaded &&
drive->cmi_drive_loaded) {
if (mm_db_exec(HERE, db,
"select \"LibraryName\",\"DriveName\" "
"from \"DRIVE\" where \"DRIVE\"."
"\"CartridgePCL\" = '%s' and "
"\"DRIVE\".\"DriveName\" = '%s';",
cur_pcl, cur_drive) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"mm_unmount_2_drive:"
" db error reading data");
mm_clear_db(&db->mm_db_results);
continue;
}
if (PQntuples(db->mm_db_results) == 0) {
/* Cur cart is not loaded */
mms_trace(MMS_ERR,
"%s not found in drive %s",
cur_pcl, cur_drive);
mm_clear_db(&db->mm_db_results);
continue;
}
mm_set_mount_info_cart(cur_cartid,
mount_info);
mm_set_mount_info_drive(cur_drive,
mount_info);
mm_set_mount_info_dm(cur_dm,
mount_info);
mm_set_mount_info_library(cur_library,
mount_info);
mms_trace(MMS_DEVP,
"** 2 Unmount Summary **");
mms_trace(MMS_DEVP,
"1st unmount %s %s",
cur_library,
cur_drive);
mms_trace(MMS_DEVP,
"2nd unmount %s %s",
PQgetvalue(db->mm_db_results, 0, 0),
PQgetvalue(db->mm_db_results, 0, 1));
mount_info->cmi_first_lib =
strdup(cur_library);
mount_info->cmi_first_drive =
strdup(cur_drive);
mount_info->cmi_second_lib =
strdup(PQgetvalue(db->mm_db_results, 0, 0));
mount_info->cmi_second_drive =
strdup(PQgetvalue(db->mm_db_results, 0, 1));
mm_clear_db(&db->mm_db_results);
return (1);
}
}
}
return (0);
}
int
mm_mount_loaded_drive(mm_command_t *cmd, mm_db_t *db,
char **drive_to_unload, char **lib_to_unload) {
/*
* this function needs to determine if a candidate
* cartridge must be mounted on a drive already loaded
* with a non-candidate cartridge that needs to be unmounted
* OR
* If a candidate cartridge is loaded in a non-candidate drive
* that 1st must be unmounted
* If there is, it must set the mount_info
* for the cart/lib/drive/dm
*/
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
cmi_cart_list_t *cart = NULL;
cmi_drive_list_t *drive = NULL;
char *cur_cartid = NULL;
char *cur_pcl = NULL;
char *cur_library = NULL;
char *cur_dm = NULL;
char *cur_drive = NULL;
mms_trace(MMS_DEVP,
"mm_mount_loaded_drive: ");
/* The list should already be ordered */
/* select the 1st available */
mms_list_foreach(&mount_info->cmi_cart_list, cart) {
if (cart->cmi_cart_not_ready) {
continue;
}
cur_library = cart->cmi_library;
cur_cartid = cart->cmi_cart_id;
cur_pcl = cart->cmi_cart_pcl;
/* If the cartridge is not mounted */
/* The list should already be ordered */
/* select the 1st available */
mms_list_foreach(&cart->cmi_drive_list, drive) {
if (drive->cmi_drive_not_ready) {
continue;
}
cur_drive = drive->cmi_drive_name;
cur_dm = drive->cmi_dm_name;
if (cart->cmi_cart_loaded &&
(drive->cmi_drive_loaded == 0)) {
/* Candidate is loaded and drive is empty */
/* this candidate cart is loaded in a drive */
/* Get the lib/drive name where */
/* this cartridge is mounted */
if (mm_db_exec(HERE, db,
"select \"LibraryName\",\"DriveName\" "
"from \"DRIVE\" where \"DRIVE\"."
"\"CartridgePCL\" = '%s';",
cur_pcl) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"mm_mount_loaded_drive: "
"db error getting data");
continue;
}
if (PQntuples(db->mm_db_results) == 0) {
/* Cur cart is not loaded */
mms_trace(MMS_ERR,
"%s not found in a drive",
cur_pcl);
mm_clear_db(&db->mm_db_results);
continue;
} else {
/* cur cart is loaded */
*(drive_to_unload) =
mms_strapp(*(drive_to_unload),
PQgetvalue(db->mm_db_results,
0, 1));
*(lib_to_unload) =
mms_strapp(*(lib_to_unload),
PQgetvalue(db->mm_db_results,
0, 0));
mms_trace(MMS_DEVP,
"%s loaded in %s %s",
cur_pcl,
PQgetvalue(db->mm_db_results,
0, 0),
PQgetvalue(db->mm_db_results,
0, 1));
}
mm_clear_db(&db->mm_db_results);
mm_set_mount_info_cart(cur_cartid,
mount_info);
mm_set_mount_info_drive(cur_drive,
mount_info);
mm_set_mount_info_dm(cur_dm,
mount_info);
mm_set_mount_info_library(cur_library,
mount_info);
return (1);
} else if ((cart->cmi_cart_loaded == 0) &&
(drive->cmi_drive_loaded == 1)) {
/* set this mount info and return */
*(drive_to_unload) = NULL;
*(lib_to_unload) = NULL;
mm_set_mount_info_cart(cur_cartid,
mount_info);
mm_set_mount_info_drive(cur_drive,
mount_info);
mm_set_mount_info_dm(cur_dm,
mount_info);
mm_set_mount_info_library(cur_library,
mount_info);
return (1);
}
}
}
return (0);
}
int
mm_set_immediate_unmount(mm_command_t *cmd, mm_db_t *db) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
cmi_cart_list_t *cart = NULL;
cmi_drive_list_t *drive = NULL;
char *cur_cartid = NULL;
char *cur_library = NULL;
char *cur_dm = NULL;
char *cur_drive = NULL;
int rc = MM_CMD_DONE;
/* The list should already be ordered */
/* select the 1st available */
cart = mms_list_head(&mount_info->cmi_cart_list);
if (cart == NULL) {
mms_trace(MMS_ERR,
"internal error setting cmi info, "
"cannot find candidate carts structfound");
mm_system_error(cmd,
"internal error setting cmi info, "
"no candidate carts found");
return (MM_CMD_ERROR);
}
cur_library = cart->cmi_library;
cur_cartid = cart->cmi_cart_id;
drive = mms_list_head(&cart->cmi_drive_list);
if (drive == NULL) {
mms_trace(MMS_ERR,
"internal error setting cmi info, "
"no candidate drives found");
mm_system_error(cmd,
"internal error setting cmi info, "
"no candidate drives found");
return (MM_CMD_ERROR);
}
cur_drive = drive->cmi_drive_name;
cur_dm = drive->cmi_dm_name;
mm_set_mount_info_cart(cur_cartid,
mount_info);
mm_set_mount_info_drive(cur_drive,
mount_info);
mm_set_mount_info_dm(cur_dm,
mount_info);
mm_set_mount_info_library(cur_library,
mount_info);
if (mount_info->cmi_pcl == NULL) {
mount_info->cmi_pcl =
mm_get_cart_pcl(cmd, mount_info->cmi_cartridge, db);
}
/* Select Is done - print the results */
mms_trace(MMS_DEVP, "Cart/Lib/Drive selection "
"complete for task %s",
cmd->cmd_uuid);
mms_trace(MMS_DEVP, "Cartridge ID is %s",
mount_info->cmi_cartridge);
mms_trace(MMS_DEVP, "Cartridge PCL is %s",
mount_info->cmi_pcl);
mms_trace(MMS_DEVP, "Library is %s",
mount_info->cmi_library);
mms_trace(MMS_DEVP, "Drive is %s",
mount_info->cmi_drive);
mms_trace(MMS_DEVP, "DM is %s",
mount_info->cmi_dm);
if (mm_db_exec(HERE, db, "delete from \"TASK\" "
"where \"TaskID\" = '%s';",
cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_unmount: "
"db error removing TASK");
}
if (mm_new_tm_task(db, cmd, "dispatched") != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_unmount: "
"db error creating TASK");
}
/* Delete all old TASK objects and create them anew */
if (mm_db_exec(HERE, db, "delete from \"TASKDRIVE\" "
"where \"TaskID\" = '%s';",
cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_unmount: "
"db error removing TASKDRIVE");
}
if (mm_db_exec(HERE, db, "delete from \"TASKLIBRARY\" "
"where \"TaskID\" = '%s';",
cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_unmount: "
"db error removing TASKLIBRARY");
}
if (mm_db_exec(HERE, db, "delete from \"TASKCARTRIDGE\" "
"where \"TaskID\" = '%s';",
cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_unmount: "
"db error removing TASKCARTRIDGE");
}
if (mm_set_tm_drive(db,
cmd->cmd_uuid,
mount_info->cmi_drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_unmount: "
"db error setting TASKDRIVE");
}
if (mm_set_tm_library(db,
cmd->cmd_uuid,
mount_info->cmi_library) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_unmount: "
"db error setting TASKLIBRARY");
}
if (mm_set_tm_cartridge(db,
cmd->cmd_uuid,
mount_info->cmi_cartridge) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_unmount: "
"db error setting TASKCARTRIDGE");
}
if (mm_db_exec(HERE, db, "update \"DRIVE\""
"set \"DriveStateSoft\" = 'in use'"
"where \"DriveName\" = '%s';",
mount_info->cmi_drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_unmount: "
"db error setting DriveStateSoft");
}
if (mm_db_exec(HERE, db, "update \"DRIVE\""
"set \"DMName\" = '%s' "
"where \"DriveName\" = '%s';",
mount_info->cmi_dm,
mount_info->cmi_drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_unmount: "
"db error setting DMName");
}
if (mm_db_exec(HERE, db,
"update \"CARTRIDGE\" set "
"\"CartridgeStatus\" = 'in use' "
"where \"CartridgeID\" = '%s';",
mount_info->cmi_cartridge) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_unmount: "
"db error setting CartridgeStatus");
}
return (rc);
}
void
mm_set_mount_objs(mm_command_t *cmd, mm_db_t *db) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
if (mm_db_exec(HERE, db, "delete from \"TASK\" "
"where \"TaskID\" = '%s';",
cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_mount_objs: "
"db error deleting TASK");
}
if (mm_new_tm_task(db, cmd, "dispatched") != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_mount_objs: "
"db error inserting TASK");
}
/* Delete all old TASK objects and create them anew */
if (mm_db_exec(HERE, db, "delete from \"TASKDRIVE\" "
"where \"TaskID\" = '%s';",
cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_mount_objs: "
"db error deleting TASKDRIVE");
}
if (mm_db_exec(HERE, db, "delete from \"TASKLIBRARY\" "
"where \"TaskID\" = '%s';",
cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_mount_objs: "
"db error deleting TASKLIBRARY");
}
if (mm_db_exec(HERE, db, "delete from \"TASKCARTRIDGE\" "
"where \"TaskID\" = '%s';",
cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_mount_objs: "
"db error deleting TASKCARTRIDGE");
}
if (mm_set_tm_drive(db,
cmd->cmd_uuid,
mount_info->cmi_drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_mount_objs: "
"db error inserting TASKDRIVE");
}
if (mm_set_tm_library(db,
cmd->cmd_uuid,
mount_info->cmi_library) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_mount_objs: "
"db error inserting TASKLIBRARY");
}
if (mm_set_tm_cartridge(db,
cmd->cmd_uuid,
mount_info->cmi_cartridge) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_mount_objs: "
"db error inserting TASKCARTRIDGE");
}
if (mm_db_exec(HERE, db, "update \"DRIVE\""
"set \"DriveStateSoft\" = 'in use'"
"where \"DriveName\" = '%s';",
mount_info->cmi_drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_mount_objs: "
"db error updating DriveStateSoft");
}
if (mm_db_exec(HERE, db, "update \"DRIVE\""
"set \"DMName\" = '%s' "
"where \"DriveName\" = '%s';",
mount_info->cmi_dm,
mount_info->cmi_drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_mount_objs: "
"db error updating DMName");
}
if (mm_db_exec(HERE, db,
"update \"CARTRIDGE\" set "
"\"CartridgeStatus\" = 'in use' "
"where \"CartridgeID\" = '%s';",
mount_info->cmi_cartridge) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_mount_objs: "
"db error updating CartridgeStatus");
}
}
int
mm_dispatch_now(mm_wka_t *mm_wka, mm_command_t *cmd, mm_db_t *db) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
mm_command_t *unmnt_cmd_1 = NULL;
mm_command_t *unmnt_cmd_2 = NULL;
/* This function is used to setup the command */
/* flags and depend pointers for the mount */
/* Need to set error message in this function */
if (mount_info->cmi_mount_type ==
MM_CANDIDATE_LOADED) {
mms_trace(MMS_DEVP,
"MM_CANDIDATE_LOADED");
/* Remove the delay unload command */
(void) mm_remove_unload(mount_info->cmi_library,
mount_info->cmi_drive,
mm_wka->mm_data);
return (0);
}
if (mount_info->cmi_mount_type ==
MM_OPEN_DRIVE) {
mms_trace(MMS_DEVP,
"MM_OPEN_DRIVE");
return (0);
}
if (mount_info->cmi_mount_type ==
MM_UNMOUNT_DRIVE) {
mms_trace(MMS_DEVP,
"MM_UNMOUNT_DRIVE");
/* Set the delay unload for immdiate dispatch */
if (mm_dispatch_unload(mount_info->cmi_library,
mount_info->cmi_drive,
cmd,
mm_wka->mm_data) == NULL) {
/* Instead of return error */
/* attempt to fix by adding a clear_drive */
/* for this drive, set this */
/* command as parent of */
/* the clear drive */
mms_trace(MMS_ERR,
"could not find delay unload, "
"attempt to clear and continue");
if (mm_add_clear_drive(mount_info->cmi_drive,
mm_wka->mm_data,
db, cmd, NULL, 1, 0) == NULL) {
mm_system_error(cmd,
"error adding clear drive cmd");
return (1);
}
}
MM_UNSET_FLAG(cmd->cmd_flags, MM_CMD_DISPATCHABLE);
return (0);
}
if (mount_info->cmi_mount_type ==
MM_UNMOUNT_CART) {
mms_trace(MMS_DEVP,
"MM_UNMOUNT_CART");
/* Set the delay unload for immdiate dispatch */
if (mm_dispatch_unload(mount_info->
cmi_first_lib,
mount_info->cmi_first_drive,
cmd,
mm_wka->mm_data) == NULL) {
/* Instead of return error */
/* attempt to fix by adding a clear_drive */
/* for this drive, set this */
/* command as parent of */
/* the clear drive */
mms_trace(MMS_ERR,
"could not find delay unload, "
"attempt to clear and continue");
if (mm_add_clear_drive(mount_info->
cmi_first_drive,
mm_wka->mm_data,
db, cmd, NULL, 1, 0) == NULL) {
mm_system_error(cmd,
"error adding clear drive cmd");
return (1);
}
}
MM_UNSET_FLAG(cmd->cmd_flags, MM_CMD_DISPATCHABLE);
return (0);
}
if (mount_info->cmi_mount_type ==
MM_UNMOUNT_2) {
mms_trace(MMS_DEVP,
"MM_UNMOUNT_2");
if ((unmnt_cmd_1 =
mm_dispatch_unload(mount_info->cmi_first_lib,
mount_info->cmi_first_drive,
NULL,
mm_wka->mm_data)) == NULL) {
mms_trace(MMS_ERR,
"error finding unmount command");
if ((unmnt_cmd_1 =
mm_add_clear_drive(mount_info->cmi_first_drive,
mm_wka->mm_data,
db, cmd, NULL, 1, 0)) == NULL) {
mm_system_error(cmd,
"error adding clear drive cmd");
return (1);
}
}
if ((unmnt_cmd_2 =
mm_return_unload(mount_info->cmi_second_lib,
mount_info->cmi_second_drive,
mm_wka->mm_data)) == NULL) {
mms_trace(MMS_ERR,
"error finding unmount command");
if ((unmnt_cmd_2 =
mm_add_clear_drive(mount_info->cmi_second_drive,
mm_wka->mm_data,
db, cmd, NULL, 1, 0)) == NULL) {
mm_system_error(cmd,
"error adding clear drive cmd");
return (1);
}
}
mm_add_depend(unmnt_cmd_1, unmnt_cmd_2);
mm_add_depend(unmnt_cmd_2, cmd);
MM_SET_FLAG(unmnt_cmd_1->cmd_flags,
MM_CMD_DISPATCHABLE);
MM_UNSET_FLAG(unmnt_cmd_2->cmd_flags,
MM_CMD_DISPATCHABLE);
MM_UNSET_FLAG(cmd->cmd_flags,
MM_CMD_DISPATCHABLE);
return (0);
}
mm_system_error(cmd,
"encountered unknown mount type");
return (1);
}
int
mm_set_immediate_mount(mm_wka_t *mm_wka, mm_command_t *cmd, mm_db_t *db) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
int rc = MM_CMD_DONE;
char *drive_to_unload = NULL;
char *lib_to_unload = NULL;
mms_trace(MMS_DEVP, "mm_set_immediate_mount");
/* select the exact cart/drive/dm/lib combination */
/* Every candidate is currently in a ready state */
/* Drives may be loaded with a cartridge */
/* Cartridge could be: */
/* a. a non-candidate cartridge */
/* b. a candidate cartridge */
/* If a candidate drive has a candidate loaded, use that now */
/* If their are no candidate cartridge's loaded, */
/* try to find an open drive */
/* If there are no open drives, use a drive loaded */
/* with a non-candidate cartridge */
if (mm_mount_candidate_loaded(cmd)) {
/* 0 mount time */
mms_trace(MMS_DEVP,
"a candidate cartridge is loaded");
mount_info->cmi_mount_type =
MM_CANDIDATE_LOADED;
} else if (mm_mount_open_drive(cmd)) {
/* 1 mount time */
mms_trace(MMS_DEVP,
"open drive found");
mount_info->cmi_mount_type =
MM_OPEN_DRIVE;
} else if (mm_mount_loaded_drive(cmd, db, &drive_to_unload,
&lib_to_unload)) {
/* 2 mount time */
/* these mounts need an unmount, then mount */
if (drive_to_unload == NULL &&
lib_to_unload == NULL) {
mount_info->cmi_mount_type =
MM_UNMOUNT_DRIVE;
mms_trace(MMS_DEVP,
"drive loaded with non-candidate "
"must unload 1st");
/* Need to set up parent command */
/* return as dispatch depend */
mms_trace(MMS_DEVP,
"%s needs unload to complete first",
mount_info->cmi_drive);
MM_UNSET_FLAG(cmd->cmd_flags,
MM_CMD_DISPATCHABLE);
rc = MM_DISPATCH_DEPEND;
} else {
mms_trace(MMS_DEVP,
"candidate loaded in non-candidate drive "
"must unload 1st");
mount_info->cmi_mount_type =
MM_UNMOUNT_CART;
mount_info->cmi_first_drive =
strdup(drive_to_unload);
mount_info->cmi_first_lib =
strdup(lib_to_unload);
/* Need to set up parent command */
/* return as dispatch depend */
mms_trace(MMS_DEVP,
"%s needs unload to complete first",
drive_to_unload);
MM_UNSET_FLAG(cmd->cmd_flags,
MM_CMD_DISPATCHABLE);
rc = MM_DISPATCH_DEPEND;
free(drive_to_unload);
free(lib_to_unload);
}
} else if (mm_unmount_2_drive(cmd, db)) {
mount_info->cmi_mount_type =
MM_UNMOUNT_2;
/* 3 mount time */
/* Candidate cart is mounted, */
/* the only candidate drive is loaded with non-candidate */
/* need to unmount candidate cart, unmount candidate drive */
/* then mount candidate cart/drive */
MM_UNSET_FLAG(cmd->cmd_flags, MM_CMD_DISPATCHABLE);
rc = MM_DISPATCH_DEPEND;
} else {
/* should never reach herer */
mms_trace(MMS_ERR,
"MMS_ERROR - no drives found");
mm_system_error(cmd,
"internal error, "
"could not find ready drive, "
"submitt a bug if you hit this!,"
"MM internal states out of sync");
mms_trace(MMS_INFO, "mm_set_immediate_mount: "
"returning MM_RESYNC");
return (MM_RESYNC);
}
if (mount_info->cmi_pcl == NULL) {
mount_info->cmi_pcl =
mm_get_cart_pcl(cmd, mount_info->cmi_cartridge, db);
}
/* call function to kick off delay unmounts */
if (mm_dispatch_now(mm_wka, cmd, db)) {
/* error should be set */
mms_trace(MMS_ERR,
"error setting up mount for dispatch");
return (MM_CMD_ERROR);
}
/* Select Is done - print the results */
mms_trace(MMS_DEVP, "Cart/Lib/Drive selection "
"complete for task %s",
cmd->cmd_uuid);
mms_trace(MMS_DEVP, "Cartridge ID is %s",
mount_info->cmi_cartridge);
mms_trace(MMS_DEVP, "Cartridge PCL is %s",
mount_info->cmi_pcl);
mms_trace(MMS_DEVP, "Library is %s",
mount_info->cmi_library);
mms_trace(MMS_DEVP, "Drive is %s",
mount_info->cmi_drive);
mms_trace(MMS_DEVP, "DM is %s",
mount_info->cmi_dm);
if (mm_db_exec(HERE, db, "delete from \"TASK\" "
"where \"TaskID\" = '%s';",
cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_mount: "
"db error removing TASK");
}
if (mm_new_tm_task(db, cmd, "dispatched") != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_mount: "
"db error creating TASK");
}
/* Delete all old TASK objects and create them anew */
if (mm_db_exec(HERE, db, "delete from \"TASKDRIVE\" "
"where \"TaskID\" = '%s';",
cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_mount: "
"db error removing TASKDRIVE");
}
if (mm_db_exec(HERE, db, "delete from \"TASKLIBRARY\" "
"where \"TaskID\" = '%s';",
cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_mount: "
"db error removing TASKLIBRARY");
}
if (mm_db_exec(HERE, db, "delete from \"TASKCARTRIDGE\" "
"where \"TaskID\" = '%s';",
cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_mount: "
"db error removing TASKCARTRIDGE");
}
if (mm_set_tm_drive(db,
cmd->cmd_uuid,
mount_info->cmi_drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_mount: "
"db error creating TASKDRIVE");
}
if (mm_set_tm_library(db,
cmd->cmd_uuid,
mount_info->cmi_library) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_mount: "
"db error creating TASKLIBRARY");
}
if (mm_set_tm_cartridge(db,
cmd->cmd_uuid,
mount_info->cmi_cartridge) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_mount: "
"db error creating TASKCARTRIDGE");
}
if (mm_db_exec(HERE, db, "update \"DRIVE\"" \
"set \"DriveStateSoft\" = 'in use'" \
"where \"DriveName\" = '%s';",
mount_info->cmi_drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_mount: "
"db error updating DriveStateSoft");
}
if (mm_db_exec(HERE, db, "update \"DRIVE\""\
"set \"DMName\" = '%s' "\
"where \"DriveName\" = '%s';",
mount_info->cmi_dm,
mount_info->cmi_drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_mount: "
"db error updating DMName");
}
if (mm_db_exec(HERE, db,
"update \"CARTRIDGE\" set "
"\"CartridgeStatus\" = 'in use' "
"where \"CartridgeID\" = '%s';",
mount_info->cmi_cartridge) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_set_immediate_mount: "
"db error updating CartridgeStatus");
}
return (rc);
}
int
mm_parse_mount_cmd(mm_wka_t *mm_wka, mm_command_t *cmd) {
cci_t *conn = &mm_wka->wka_conn;
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
mms_par_node_t *arg;
mms_par_node_t *value;
mms_par_node_t *work = NULL;
mms_par_node_t *item = NULL;
int go;
int count;
char *dm_host;
cmi_mode_list_t *mode = NULL;
mms_trace(MMS_DEVP, "mm_parse_mount_cmd");
mount_info->cmi_operation = MM_MOUNT;
/* Get the type */
mms_trace(MMS_DEVP, "type");
MMS_PN_LOOKUP(arg, cmd->cmd_root, "type",
MMS_PN_CLAUSE, NULL);
MMS_PN_LOOKUP(value, arg, NULL, MMS_PN_KEYWORD, NULL);
if (strcmp(value->pn_string, "SIDE") == 0) {
mount_info->cmi_type = MM_SIDE;
} else if (strcmp(value->pn_string, "PARTITION") == 0) {
mount_info->cmi_type = MM_PARTITION;
} else if (strcmp(value->pn_string, "VOLUME") == 0) {
mount_info->cmi_type = MM_VOLUME;
} else {
mms_trace(MMS_ERR, "Invalid mount type specified");
mm_response_error(cmd,
EINVALIDTYPE,
ESYNTAX,
5051,
MESS_END);
return (MM_CMD_ERROR);
}
/* Get when */
mms_trace(MMS_DEVP, "when");
arg = mms_pn_lookup(cmd->cmd_root, "when",
MMS_PN_CLAUSE, NULL);
if (arg != NULL) {
MMS_PN_LOOKUP(value,
arg, NULL, MMS_PN_KEYWORD, NULL);
if (strcmp(value->pn_string, "blocking") == 0) {
mount_info->cmi_when = MM_BLOCKING;
} else {
mount_info->cmi_when = MM_IMMEDIATE;
}
} else {
/* when is optional and defaults to immediate */
mount_info->cmi_when = MM_IMMEDIATE;
}
/* Get where */
mms_trace(MMS_DEVP, "where");
work = NULL;
arg = mms_pn_lookup(cmd->cmd_root, "where",
MMS_PN_CLAUSE, &work);
if (arg != NULL) {
MMS_PN_LOOKUP(value, arg, NULL,
MMS_PN_STRING, NULL);
if (value->pn_string != NULL) {
dm_host = value->pn_string;
} else {
dm_host = mm_cci_host_ident(conn);
}
} else {
mms_trace(MMS_DEVP, "Didn't find a where clause...");
dm_host = mm_cci_host_ident(conn);
}
mount_info->cmi_where = mm_host_ident(dm_host);
mms_trace(MMS_DEVP, "where %s", mount_info->cmi_where);
/* Get File Name - Optional */
mms_trace(MMS_DEVP, "filename");
work = NULL;
arg = mms_pn_lookup(cmd->cmd_root, "filename",
MMS_PN_CLAUSE, &work);
if (arg != NULL) {
MMS_PN_LOOKUP(value, arg, NULL,
MMS_PN_STRING, NULL);
if (value->pn_string != NULL) {
mount_info->cmi_filename =
strdup(value->pn_string);
} else {
mount_info->cmi_filename = NULL;
}
} else {
mms_trace(MMS_DEVP, "Didn't find a filename clause...");
mount_info->cmi_filename = NULL;
}
/* Get BlockSize - Optional */
mms_trace(MMS_DEVP, "blocksize");
work = NULL;
arg = mms_pn_lookup(cmd->cmd_root, "blocksize",
MMS_PN_CLAUSE, &work);
if (arg != NULL) {
MMS_PN_LOOKUP(value, arg, NULL,
MMS_PN_STRING, NULL);
if (value->pn_string != NULL) {
mount_info->cmi_blocksize =
strdup(value->pn_string);
} else {
mount_info->cmi_blocksize = NULL;
}
} else {
mms_trace(MMS_DEVP, "Didn't find a blocksize clause...");
mount_info->cmi_blocksize = NULL;
}
/* Get volumeid - Optional */
mms_trace(MMS_DEVP, "volumeid");
work = NULL;
arg = mms_pn_lookup(cmd->cmd_root, "volumeid",
MMS_PN_CLAUSE, &work);
if (arg != NULL) {
MMS_PN_LOOKUP(value, arg, NULL,
MMS_PN_STRING, NULL);
if (value->pn_string != NULL) {
mount_info->cmi_volumeid =
strdup(value->pn_string);
} else {
mount_info->cmi_volumeid = NULL;
}
} else {
mms_trace(MMS_DEVP, "Didn't find a volumeid clause...");
mount_info->cmi_volumeid = NULL;
}
/* Get filesequence - Optional */
mms_trace(MMS_DEVP, "filesequence");
work = NULL;
arg = mms_pn_lookup(cmd->cmd_root, "filesequence",
MMS_PN_CLAUSE, &work);
if (arg != NULL) {
MMS_PN_LOOKUP(value, arg, NULL,
MMS_PN_STRING, NULL);
if (value->pn_string != NULL) {
mount_info->cmi_filesequence =
strdup(value->pn_string);
} else {
mount_info->cmi_filesequence = NULL;
}
} else {
mms_trace(MMS_DEVP, "Didn't find a filesequence clause...");
mount_info->cmi_filesequence = NULL;
}
/* Get user - Optional */
mms_trace(MMS_DEVP, "user");
work = NULL;
arg = mms_pn_lookup(cmd->cmd_root, "user",
MMS_PN_CLAUSE, &work);
if (arg != NULL) {
MMS_PN_LOOKUP(value, arg, NULL,
MMS_PN_STRING, NULL);
if (value->pn_string != NULL) {
mount_info->cmi_user =
strdup(value->pn_string);
} else {
mount_info->cmi_user = NULL;
}
} else {
mms_trace(MMS_DEVP, "Didn't find a user clause...");
mount_info->cmi_user = NULL;
}
/* Get First Mount Clause */
mms_trace(MMS_DEVP, "firstmount");
work = NULL;
arg = mms_pn_lookup(cmd->cmd_root, "firstmount",
MMS_PN_CLAUSE, &work);
item = NULL;
if (arg != NULL) {
count = 0;
go = 1;
while (go) {
if ((value =
mms_pn_lookup(arg, NULL,
MMS_PN_STRING,
&item)) == NULL) {
go = 0;
} else {
mount_info->cmi_firstmount[count] =
value->pn_string;
count ++;
}
}
mount_info->cmi_num_firstmount = count;
} else {
mms_trace(MMS_DEVP, "Didin't find a first mount clause");
}
/* Get Access Mode Clause */
mms_trace(MMS_DEVP, "accessmode");
work = NULL;
for (arg = mms_pn_lookup(cmd->cmd_root, "accessmode",
MMS_PN_CLAUSE, &work);
arg != NULL;
arg = mms_pn_lookup(cmd->cmd_root, "accessmode",
MMS_PN_CLAUSE, &work)) {
/* Malloc a new mode object */
mode = (cmi_mode_list_t *)
calloc(1, sizeof (cmi_mode_list_t));
if (mode == NULL) {
mms_trace(MMS_ERR,
"Unable to malloc cmi_mode_list: %s",
strerror(errno));
mm_system_error(cmd,
"unable to allocate "
"memory for mode list");
return (MM_CMD_ERROR);
}
/* Get all of the access Mode tokens */
item = NULL;
count = 0;
go = 1;
while (go) {
if ((value =
mms_pn_lookup(arg, NULL,
MMS_PN_STRING,
&item)) == NULL) {
go = 0;
} else {
mode->cmi_accessmode[count] =
value->pn_string;
count ++;
}
}
/* Put this access mode into the Accessmode list */
mount_info->cmi_total_modes ++;
mode->cmi_num_accessmode = count;
mms_list_insert_tail(&mount_info->cmi_mode_list, mode);
}
/* Get retention clause */
/* Get user - Optional */
mms_trace(MMS_DEVP, "retention");
work = NULL;
arg = mms_pn_lookup(cmd->cmd_root, "retention",
MMS_PN_CLAUSE, &work);
if (arg != NULL) {
MMS_PN_LOOKUP(value, arg, NULL,
MMS_PN_STRING, NULL);
if (value->pn_string != NULL) {
mount_info->cmi_retention =
strdup(value->pn_string);
} else {
mount_info->cmi_retention = NULL;
}
} else {
mms_trace(MMS_DEVP, "Didn't find a retention clause");
mount_info->cmi_retention = NULL;
}
return (MM_CMD_DONE);
not_found:
mm_response_error(cmd,
ECLASS_LANGUAGE,
ENOTFOUND,
5062,
MESS_END);
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
return (MM_CMD_ERROR);
no_mem:
MM_ABORT_NO_MEM();
return (MM_CMD_ERROR);
}
void
mm_mount_clean_candidates(mm_command_t *cmd) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
cmi_cart_list_t *cart = NULL;
cmi_drive_list_t *drive = NULL;
int has_drive = 0;
cmi_cart_list_t *next_cart;
cmi_drive_list_t *next_drive;
mms_trace(MMS_DEVP, "mm_mount_clean_candidates");
/* Cannot use mms_list_foreach when removing list elements */
/* For each cart */
for (cart = mms_list_head(&mount_info->
cmi_cart_list);
cart != NULL;
cart = next_cart) {
next_cart =
mms_list_next(&mount_info->
cmi_cart_list,
cart);
mms_trace(MMS_DEVP, " check cart %s",
cart->cmi_cart_pcl);
has_drive = 0;
/* For each drive */
for (drive = mms_list_head(&cart->
cmi_drive_list);
drive != NULL;
drive = next_drive) {
next_drive =
mms_list_next(&cart->
cmi_drive_list,
drive);
mms_trace(MMS_DEVP, " check drive %s",
drive->cmi_drive_name);
if (drive->cmi_remove_drive) {
mms_list_remove(&cart->
cmi_drive_list,
drive);
mms_trace(MMS_DEVP,
" free drive %s",
drive->cmi_drive_name);
mm_free_cmi_drive(drive);
} else {
mms_trace(MMS_DEVP,
" drive good, %s",
drive->cmi_drive_name);
has_drive = 1;
}
}
if (has_drive == 0)
cart->cmi_remove_cart = 1;
if (cart->cmi_remove_cart) {
mms_list_remove(&mount_info->cmi_cart_list, cart);
mms_trace(MMS_DEVP,
" free cart, %s",
cart->cmi_cart_pcl);
mm_free_cmi_cart(cart);
} else {
mms_trace(MMS_DEVP,
" cart good, %s",
cart->cmi_cart_pcl);
}
}
}
int
mm_mount_check_candidates(mm_wka_t *mm_wka, mm_command_t *cmd,
mm_db_t *db) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
cmi_cart_list_t *cart = NULL;
cmi_drive_list_t *drive = NULL;
char *candidate_cartid = NULL;
char *candidate_drive = NULL;
mms_list_foreach(&mount_info->cmi_cart_list, cart) {
candidate_cartid = cart->cmi_cart_id;
mms_trace(MMS_INFO, "Check Cartridge, %s",
candidate_cartid);
if (mm_candidate_cartridge_ok(mm_wka,
cmd, db,
cart)) {
/* Cartridge is ok */
if (cart->cmi_cart_not_ready) {
mms_trace(MMS_DEVP,
"cartridge %s is not "
"ready/in use",
candidate_cartid);
} else {
mms_trace(MMS_DEVP,
"Cartridge, %s, is available",
candidate_cartid);
}
} else {
/* Cartridge not available */
mms_trace(MMS_DEVP,
"Cartridge, %s, is not "
"available for mount",
candidate_cartid);
cart->cmi_remove_cart = 1;
/* Go on to next cartridge */
continue;
}
mms_list_foreach(&cart->cmi_drive_list, drive) {
candidate_drive = drive->cmi_drive_name;
if (cart->cmi_cart_not_ready) {
drive->cmi_drive_not_ready = 1;
continue;
}
mms_trace(MMS_INFO,
"Check Drive, %s", candidate_drive);
if (mm_candidate_drive_ok(mm_wka,
cmd, db,
candidate_cartid,
drive)) {
if (drive->cmi_drive_not_ready) {
mms_trace(MMS_DEVP,
"Drive, %s, is not ready/in use",
candidate_drive);
} else {
mms_trace(MMS_DEVP,
"Drive, %s, is available",
candidate_drive);
}
} else {
mms_trace(MMS_DEVP,
"Drive, %s, not available"
" for mounts",
candidate_drive);
drive->cmi_remove_drive = 1;
}
}
}
mm_mount_clean_candidates(cmd);
return (0);
}
int
mm_mount_init_candidates(mm_command_t *cmd,
PGresult *cart_results, mm_db_t *db) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
cmi_cart_list_t *cur_cart;
int cart_rows;
int cart_row;
int drive_rows;
int drive_row;
char *candidate_library = NULL;
char *candidate_drive = NULL;
char *candidate_cartid = NULL;
PGresult *drive_results;
cart_rows = PQntuples(cart_results);
mm_free_cmi_cart_list(&mount_info->cmi_cart_list);
for (cart_row = 0; cart_row < cart_rows; cart_row ++) {
candidate_cartid = PQgetvalue(cart_results, cart_row, 0);
candidate_library = PQgetvalue(cart_results, cart_row, 1);
mms_trace(MMS_DEVP,
"mm_mount_init_candidates: cartid = %s, library = %s",
candidate_cartid, candidate_library);
/* Allocate this cartridge */
cur_cart = NULL;
cur_cart = mm_setup_cart(cmd,
db,
cart_results,
cart_row);
if (cur_cart == NULL) {
mms_trace(MMS_ERR, "error allocing candidate cart");
mm_system_error(cmd,
"error allocing candidate cart");
return (1);
}
mms_trace(MMS_INFO, "Check Library, %s",
candidate_library);
if (mm_candidate_library_ok(cmd, db,
candidate_library)) {
mms_trace(MMS_DEVP,
"Library, %s, is available",
candidate_library);
} else {
mms_trace(MMS_DEVP,
"Library, %s, not available",
candidate_library);
cur_cart->cmi_remove_cart = 1;
/* Go on to next cartridge */
continue;
}
/* Get the drives in this library */
/* Do some ordering of drives here */
/* mm_mount_order_candidates will do the ordering */
if (cmd->cmd_func == mm_mount_cmd_func) {
if (mm_db_exec(HERE, db,
"select distinct \"DriveName\","
"\"LibraryName\",\"DrivePriority\","
"\"DriveNumberMounts\" from ("
"select \"DriveName\",\"LibraryName\","
"\"DrivePriority\",\"DriveNumberMounts\""
"from \"DRIVE\""
"where (\"DRIVE\".\"LibraryName\" = '%s')"
"order by \"DRIVE\".\"DriveNumberMounts\""
") as foo order by \"DrivePriority\";",
candidate_library) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"db error, init candidate cart");
mm_sql_db_err_rsp_new(cmd, db);
return (1);
}
} else {
if (mm_db_exec(HERE, db,
"select distinct \"DriveName\","
"\"LibraryName\",\"DrivePriority\","
"\"DriveNumberMounts\" from ("
"select \"DriveName\",\"LibraryName\","
"\"DrivePriority\",\"DriveNumberMounts\""
"from \"DRIVE\""
"where (\"DRIVE\".\"LibraryName\" = '%s' "
"and \"DRIVE\".\"CartridgePCL\" = '%s')"
"order by \"DRIVE\".\"DriveNumberMounts\""
") as foo order by \"DrivePriority\";",
candidate_library,
cur_cart->cmi_cart_pcl) != MM_DB_DATA) {
mms_trace(MMS_ERR,
"db error, init candidate cart");
mm_sql_db_err_rsp_new(cmd, db);
return (1);
}
}
drive_results = db->mm_db_results;
drive_rows = PQntuples(drive_results);
if (drive_rows == 0) {
mms_trace(MMS_ERR,
"couldn't match any drives for library %s",
candidate_library);
mm_response_error(cmd,
ECLASS_EXPLICIT, ENOMATCH,
5094,
"lib",
candidate_library,
MESS_END);
mm_clear_db(&drive_results);
return (1);
}
for (drive_row = 0; drive_row < drive_rows; drive_row ++) {
candidate_drive = PQgetvalue(drive_results,
drive_row, 0);
mms_trace(MMS_DEVP,
"mm_mount_init_candidates: drive = %s",
candidate_drive);
/* mm_set_dirve_unmount and */
/* mm_setup_drive return a pointer */
/* to the set up drive struct */
if (mount_info->cmi_operation == MM_UNMOUNT) {
(void) mm_setup_drive_unmount(cmd,
db,
cur_cart,
drive_results,
drive_row);
} else {
(void) mm_setup_drive(cmd,
db,
cur_cart,
drive_results,
drive_row);
}
}
mm_clear_db(&drive_results);
}
mm_mount_clean_candidates(cmd);
return (0);
}
PGresult* mm_mount_cart_results(mm_wka_t *mm_wka,
mm_command_t *cmd, mm_db_t *db) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
char *path_buf = NULL;
char *tmp_buf = NULL;
cci_t *conn = &mm_wka->wka_conn;
char *app_name = conn->cci_client;
int i;
mm_clear_source(cmd);
mm_clear_dest(cmd);
mm_clear_const(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);
}
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);
}
if (cmd->wka_ptr->wka_privilege == MM_PRIV_STANDARD) {
/* add CARTRIDGEGROUPAPPLICATION constraint */
(void) mm_add_to_dest(cmd,
"CARTRIDGEGROUPAPPLICATION");
if (tmp_buf)
free(tmp_buf);
tmp_buf = NULL;
tmp_buf = mms_strapp(tmp_buf,
"\"CARTRIDGEGROUPAPPLICATION\"."
"\"ApplicationName\" = '%s'",
app_name);
(void) mm_add_to_const(cmd, tmp_buf);
if (tmp_buf)
free(tmp_buf);
tmp_buf = NULL;
}
/* Clear cmd_buf */
if (cmd->cmd_buf)
SQL_CHK_LEN(&cmd->cmd_buf, NULL,
&cmd->cmd_bufsize, 0);
/* Make path_buf and set source */
path_buf = mms_strapp(path_buf,
"select distinct");
if (mount_info->cmi_type == MM_VOLUME) {
if (mm_add_char("VOLUME",
&cmd->cmd_source_list)) {
mms_trace(MMS_ERR,
"mm_mount_cart_results: "
"Error adding char to source list");
mm_system_error(cmd,
"out of mem adding to source list");
return (NULL);
}
path_buf = mms_strapp(path_buf,
"\"VOLUME\"");
}
if (mount_info->cmi_type == MM_PARTITION) {
if (mm_add_char("PARTITION",
&cmd->cmd_source_list)) {
mms_trace(MMS_ERR,
"mm_mount_cart_results: "
"Error adding char to source list");
mm_system_error(cmd,
"out of mem adding to source list");
return (NULL);
}
path_buf = mms_strapp(path_buf,
"\"PARTITION\"");
}
if (mount_info->cmi_type == MM_SIDE) {
if (mm_add_char("SIDE",
&cmd->cmd_source_list)) {
mms_trace(MMS_ERR,
"mm_mount_cart_results: "
"Error adding char to source list");
mm_system_error(cmd,
"out of mem adding to source list");
return (NULL);
}
path_buf = mms_strapp(path_buf,
"\"SIDE\"");
}
if (tmp_buf != NULL) {
free(tmp_buf);
tmp_buf = NULL;
}
/* Put path_buf into cmd_buf */
path_buf = mms_strapp(path_buf,
".\"CartridgeID\" from\n");
SQL_CHK_LEN(&cmd->cmd_buf, NULL,
&cmd->cmd_bufsize, strlen(path_buf) + 1);
strcpy(cmd->cmd_buf, path_buf);
free(path_buf);
path_buf = NULL;
cmd->cmd_source_num = 1;
/* Make report funcs */
if (mm_sql_from_where(cmd, db)) {
mms_trace(MMS_ERR,
"mm_mount_cart_results: "
"db error creating helper functions");
return (NULL);
}
if (mm_db_exec(HERE, db, cmd->cmd_buf) != MM_DB_DATA) {
mm_sql_db_err_rsp_new(cmd, db);
mms_trace(MMS_ERR,
"db error getting candidate cartridges");
return (NULL);
}
if (PQntuples(db->mm_db_results) == 0) {
/* no cartridge matches */
mms_trace(MMS_INFO,
"match statment in mount "
"didn't match any cartridge/volumes");
mm_response_error(cmd,
ECLASS_EXPLICIT, ENOMATCH,
5052,
MESS_END);
mm_clear_db(&db->mm_db_results);
return (NULL);
}
/* Order cartridges based on priority and last time mounted */
/* Additional Cartridge Ordering */
/* done in mm_mount_order_candidates */
tmp_buf = mms_strapp(tmp_buf,
"select distinct \"CartridgeID\","
"\"LibraryName\",\"CartridgeGroupPriority\","
"\"CartridgeNumberMounts\", "
"\"CartridgeShapeName\",\"CartridgePCL\", "
"\"CartridgeDriveOccupied\" "
"from ( "
"select \"CartridgeID\",\"LibraryName\", "
"\"CartridgeGroupPriority\","
"\"CartridgeNumberMounts\", "
"\"CartridgeShapeName\",\"CartridgePCL\", "
"\"CartridgeDriveOccupied\" "
"from \"CARTRIDGE\","
"\"CARTRIDGEGROUP\",\"CARTRIDGETYPE\" ");
for (i = 0; i < PQntuples(db->mm_db_results); i++) {
if (i == 0) {
tmp_buf = mms_strapp(tmp_buf, "where (");
} else {
tmp_buf = mms_strapp(tmp_buf, "or ");
}
tmp_buf = mms_strapp(tmp_buf, " (\"CartridgeID\" = '%s')",
PQgetvalue(db->mm_db_results, i, 0));
}
tmp_buf = mms_strapp(tmp_buf,
") and"
"(\"CARTRIDGEGROUP\".\"CartridgeGroupName\" "
"= \"CARTRIDGE\".\"CartridgeGroupName\")"
"and"
"(\"CARTRIDGE\".\"CartridgeTypeName\" "
"= \"CARTRIDGETYPE\".\"CartridgeTypeName\")"
"order by \"CARTRIDGE\".\"CartridgeTimeMountedLast\""
") as foo order by \"CartridgeGroupPriority\";");
mm_clear_db(&db->mm_db_results);
if (mm_db_exec(HERE, db, tmp_buf) != MM_DB_DATA) {
free(tmp_buf);
mm_sql_db_err_rsp_new(cmd, db);
return (NULL);
}
free(tmp_buf);
return (db->mm_db_results);
no_mem:
MM_ABORT_NO_MEM();
return (NULL);
}
int
mm_mount_ready(mm_wka_t *mm_wka, mm_command_t *cmd, mm_db_t *db, int is_retry) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
PGresult *cart_results;
int cart_rows;
cmi_cart_list_t *cart = NULL;
cmi_drive_list_t *drive = NULL;
int found_cart_drive = 0;
int found_ready_cart_drive = 0;
int rc;
int resync_tries = 5;
int i = 0;
/* Do drive/cart/lib selection using path matching */
if ((cart_results = mm_mount_cart_results(mm_wka,
cmd, db)) == NULL) {
/* No carts or error */
return (MM_MOUNT_ERROR);
}
cart_rows = PQntuples(cart_results);
mms_trace(MMS_DEVP, "Number of Cartridges is %d", cart_rows);
if (cart_rows == 0) {
/* No Cartridge Matches Error */
mms_trace(MMS_INFO,
"match statment in mount "
"didn't match any cartridge/volumes");
mm_response_error(cmd,
ECLASS_EXPLICIT, ENOMATCH,
5052,
MESS_END);
mm_clear_db(&cart_results);
return (MM_MOUNT_ERROR);
}
/* Create the list objects for */
/* every cartridge/drive candidate */
if (mm_mount_init_candidates(cmd, cart_results,
db)) {
mms_trace(MMS_ERR,
"error initializing candidate lists");
/* err buf should be set by mm_mount_init */
/* so return and remove */
mm_clear_db(&cart_results);
return (MM_MOUNT_ERROR);
}
mms_trace(MMS_DEVP, "candidate list created, check availability ");
mm_clear_db(&cart_results);
/* Check the availability of the candidates */
if (mm_mount_check_candidates(mm_wka, cmd,
db)) {
mms_trace(MMS_ERR,
"error checking candidate lists");
mm_system_error(cmd,
"error checking candidate lists");
return (MM_MOUNT_ERROR);
}
mms_trace(MMS_DEVP, "done checking list");
/* Print mount information */
mm_print_mount_summary(mm_wka, cmd);
/*
* For blocking mounts,
* check that at least some cart/drive combo exists
* if that cart/drive exists, but is not ready, return not ready
*
* for immediate mounts, check that at least one combination exists
*/
found_cart_drive = 0;
found_ready_cart_drive = 0;
/* if cart/drive is not reay, set for remove */
mms_list_foreach(&mount_info->cmi_cart_list, cart) {
if (cart->cmi_cart_not_ready)
cart->cmi_remove_cart = 1;
mms_list_foreach(&cart->cmi_drive_list, drive) {
found_cart_drive = 1;
if ((cart->cmi_cart_not_ready == 0) &&
(drive->cmi_drive_not_ready == 0)) {
found_ready_cart_drive = 1;
}
if (drive->cmi_drive_not_ready)
drive->cmi_remove_drive = 1;
}
}
/* If there is a library or drive error */
/* the error buff has already been set */
if (found_cart_drive == 0) {
mms_trace(MMS_INFO,
"No candidate "
"cartridge/library/drive "
"combination found");
return (MM_MOUNT_ERROR);
}
if (found_ready_cart_drive == 0) {
mms_trace(MMS_INFO,
"candidate "
"cartridge/library/drive "
"combination found, but is not ready");
return (MM_MOUNT_NOT_READY);
}
/* There is a ready cart/drive */
/* we may have set some non ready for remove */
/* so call the clean func before contine */
mm_mount_clean_candidates(cmd);
cmd->cmd_state = 1;
rc = mm_set_immediate_mount(mm_wka, cmd, db);
if (rc == MM_RESYNC) {
if (is_retry) {
return (rc);
}
/* Destroy all cart lists */
mms_trace(MMS_INFO,
"mm_mount_ready: "
"states out of sync, attempt to resync this mount");
for (i = 0; i < resync_tries; i++) {
mm_free_cmi_cart_list(&mount_info->cmi_cart_list);
rc = mm_mount_ready(mm_wka, cmd, db, 1);
if (rc != MM_RESYNC) {
mms_trace(MMS_INFO,
"mm_mount_ready: "
"resync successful");
return (rc);
}
}
mms_trace(MMS_INFO,
"mm_mount_ready: "
"states out of sync, resync failed");
return (MM_MOUNT_ERROR);
}
if (rc == MM_CMD_ERROR) {
mms_trace(MMS_ERR,
"error setting up immediate mount");
return (MM_MOUNT_ERROR);
} else if (rc == MM_DISPATCH_DEPEND) {
/* this immediate mount needs to */
/* wait for an unload */
mms_trace(MMS_DEVP,
" mount waiting "
"for unload to complete");
return (MM_MOUNT_NEED_UNLOAD);
}
mms_trace(MMS_DEVP,
"mount ready for dispatch");
return (MM_MOUNT_READY);
db_error:
mm_sql_db_err_rsp_new(cmd, db);
return (MM_MOUNT_ERROR);
}
int
mm_mount_cmd_func(mm_wka_t *mm_wka, mm_command_t *cmd)
{
mm_db_t *db = &mm_wka->mm_data->mm_db;
cci_t *conn = &mm_wka->wka_conn;
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
int rows;
int rc;
char *response_message = NULL;
mm_command_t *dmp_release = NULL;
mms_trace(MMS_DEVP, "mm mount cmd state %d", cmd->cmd_state);
if (cmd->cmd_state == 0) {
mms_trace(MMS_INFO, "Processing Mount Request...");
/*
* Generate Candidate Cartridge and Drive lists
* First parse and save the mount info
* then use SQL queries to gereate the lists
*/
mount_info->cmi_mount_cart_loaded = 0;
mount_info->cmi_fail_type = NONE;
if (mm_parse_mount_cmd(mm_wka, cmd) == MM_CMD_ERROR) {
mms_trace(MMS_ERR,
"error parsing mount command");
/* Error buf should already be set */
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
return (MM_CMD_ERROR);
}
mms_trace(MMS_DEVP, "done parsing");
/* ***DONE PARSING MOUNT COMMAND*** */
if (mount_info->cmi_when == MM_BLOCKING) {
if (mm_set_tm_task(db, cmd) != MM_DB_OK) {
goto db_error;
}
mms_trace(MMS_DEVP,
"blocking mount will be passed to task manager");
return (MM_WORK_TODO);
}
/* This is an immediate mount */
rc = mm_mount_ready(mm_wka, cmd, db, 0);
switch (rc) {
case MM_MOUNT_ERROR:
/* Error code should be set */
mms_trace(MMS_ERR,
"internal error, mm_mount_ready");
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
return (MM_CMD_ERROR);
case MM_MOUNT_READY:
/* The mount is ready, mount_info should be set */
/* continue to state 1 */
cmd->cmd_state = 1;
mms_trace(MMS_DEVP,
"mount is ready to go, "
"continue to state 1");
break;
case MM_MOUNT_NEED_UNLOAD:
/* this immediate mount needs to */
/* wait for an unload */
cmd->cmd_state = 1;
mms_trace(MMS_DEVP,
"mount waiting "
"for unload to complete");
return (MM_DISPATCH_DEPEND);
case MM_MOUNT_NOT_READY:
/* Error code should be set */
mms_trace(MMS_ERR,
"immediate mount not ready, "
"send error to client");
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
return (MM_CMD_ERROR);
default:
mms_trace(MMS_ERR,
"bad rc mm_mount_ready");
mm_system_error(cmd,
"bad rc mm_mount_ready");
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
return (MM_CMD_ERROR);
}
}
start:
if (cmd->cmd_state == 1) {
mms_trace(MMS_INFO, "Mounting tape...");
/* Reserve the DM */
/*
* mm_sql_update_state(mm_wka->mm_data, "DM",
* "DMStateSoft",
* "reserved", "DMName",
* mount_info->cmi_dm);
*/
mm_sql_update_state(mm_wka->mm_data, "DRIVE",
"DMName",
mount_info->cmi_dm, "DriveName",
mount_info->cmi_drive);
/* Add activate command */
if (mm_dmp_add_cmd(mm_wka, cmd, mount_info->cmi_dm,
MM_DMP_RESERVE) == NULL) {
mms_trace(MMS_ERR,
"error adding dmp reserve");
mm_system_error(cmd,
"error adding dmp reserve");
goto reset_states;
}
cmd->cmd_state = 3;
return (MM_DISPATCH_DEPEND);
} else if (cmd->cmd_state == 3) {
/*
* Mount cartridge in the library drive
*/
mm_command_t *lmp_mnt_cmd;
mm_wka_t *lm_wka;
uuid_text_t new_task;
char *cart_pcl;
char *side_name;
/*
* DM Activate failed
*/
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
mms_trace(MMS_DEVP, "DM reserve failed");
/* Reset drive and cartridge */
/* return error to client */
mount_info->cmi_reset_states = 1;
goto lm_dm_error;
}
if (mount_info->cmi_mount_cart_loaded) {
/* Skip lmp mount */
cmd->cmd_state = 4;
goto start;
}
/*
* Cartridge pcl and side name
*/
if ((cart_pcl = mm_get_cart_pcl(cmd,
cmd->cmd_mount_info.cmi_cartridge, db)) == NULL) {
/* Error buf should be set in mm_get_cart_pcl */
goto reset_states;
}
/* TODO side name needs to be generated in candidate query */
if ((side_name = cmd->cmd_mount_info.cmi_side_name) == NULL) {
side_name = "side 1";
}
/*
* LMP mount command
*/
lm_wka = mm_library_lm_wka(cmd->wka_ptr->mm_data,
cmd->cmd_mount_info.cmi_library, NULL);
if ((lmp_mnt_cmd = mm_alloc_cmd(lm_wka)) == NULL) {
mms_trace(MMS_ERR,
"Unable to malloc mm_command_t: %s",
strerror(errno));
mm_system_error(cmd,
"Unable to malloc lmp mount cmd");
goto reset_states;
}
lmp_mnt_cmd->cmd_func = mm_lmp_mount_cmd_func;
mm_get_uuid(new_task);
lmp_mnt_cmd->cmd_textcmd = mms_strnew(LMP_MOUNT, new_task,
cart_pcl, cart_pcl, side_name,
cmd->cmd_mount_info.cmi_drive);
lmp_mnt_cmd->cmd_root =
mm_text_to_par_node(lmp_mnt_cmd->cmd_textcmd,
mms_lmpm_parse);
lmp_mnt_cmd->cmd_task = mm_get_task(lmp_mnt_cmd->cmd_root);
mm_add_depend(lmp_mnt_cmd, cmd);
lmp_mnt_cmd->cmd_name = strdup("lmp mount");
lmp_mnt_cmd->cmd_mount_info.cmi_drive =
strdup(cmd->cmd_mount_info.cmi_drive);
lmp_mnt_cmd->cmd_mount_info.cmi_cartridge =
strdup(cmd->cmd_mount_info.cmi_cartridge);
cmd->cmd_state = 4;
pthread_mutex_lock(&mm_wka->mm_data->mm_queue_mutex);
mms_list_insert_tail(&mm_wka->mm_data->mm_cmd_queue,
lmp_mnt_cmd);
pthread_mutex_unlock(&mm_wka->mm_data->mm_queue_mutex);
free(cart_pcl);
return (MM_DISPATCH_DEPEND);
} else if (cmd->cmd_state == 4) {
/*
* LMP Mount command failed
*/
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
mms_trace(MMS_DEVP, "lm mount failed");
/* Reset drive and cartridge */
/* return error to client */
mount_info->cmi_reset_states = 1;
mount_info->cmi_need_clear = 1;
/* DM is reserved, release the DM */
if (dmp_release = mm_dmp_add_cmd(mm_wka,
cmd, mount_info->cmi_dm,
MM_DMP_RELEASE)) {
/* run withtout parent */
mm_remove_all_depend(dmp_release);
}
/* Generate error message */
response_message =
mm_ret_response_msg(cmd);
mm_response_error(cmd,
"subop", "ELMPMOUNT", 5018,
"cartridge", mount_info->cmi_cartridge,
"drive", mount_info->cmi_drive,
"msg_rsp", response_message,
MESS_END);
free(response_message);
/* Set cmd for remove, send message to client */
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn,
cmd->cmd_buf);
rc = MM_CMD_ERROR;
goto end;
}
if (mm_dmp_add_cmd(mm_wka, cmd, mount_info->cmi_dm,
MM_DMP_PRIV) == NULL) {
mms_trace(MMS_ERR,
"error adding dmp private");
mm_system_error(cmd,
"error adding dmp private");
goto reset_states;
}
cmd->cmd_state = 5;
return (MM_DISPATCH_DEPEND);
} else if (cmd->cmd_state == 5) {
/* DM_load state */
/*
* Private has finished, add a load command to the
* queue
*/
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
mms_trace(MMS_DEVP, "mmp_mount-> DMP private error");
/* Reset drive and cartridge */
/* return error to client */
mount_info->cmi_reset_states = 1;
mount_info->cmi_need_clear = 1;
/* DM is reserved, release the DM */
if (dmp_release = mm_dmp_add_cmd(mm_wka,
cmd, mount_info->cmi_dm,
MM_DMP_RELEASE)) {
/* run withtout parent */
mm_remove_all_depend(dmp_release);
}
goto lm_dm_error;
}
if (mm_dmp_add_cmd(mm_wka, cmd, mount_info->cmi_dm,
MM_DMP_LOAD) == NULL) {
mms_trace(MMS_ERR,
"error adding dmp load");
mm_system_error(cmd,
"error adding dmp load");
goto reset_states;
}
cmd->cmd_state = 6;
return (MM_DISPATCH_DEPEND);
} else if (cmd->cmd_state == 6) {
/* load command has finished, add an attach */
/* Update Drive Table */
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
mms_trace(MMS_DEVP, "mmp_mount-> DMP load error");
/* Reset drive and cartridge */
/* return error to client */
mount_info->cmi_reset_states = 1;
mount_info->cmi_need_clear = 1;
/* DM is reserved, release the DM */
if (dmp_release = mm_dmp_add_cmd(mm_wka,
NULL, mount_info->cmi_dm,
MM_DMP_RELEASE)) {
/* run withtout parent */
mm_remove_all_depend(dmp_release);
}
response_message =
mm_ret_response_msg(cmd);
mm_response_error(cmd,
ECLASS_SUBOP,
"EDMPLOAD",
5053,
"cartridge",
mount_info->cmi_cartridge,
"drive",
mount_info->cmi_drive,
"msg_rsp",
response_message,
MESS_END);
free(response_message);
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn,
cmd->cmd_buf);
rc = MM_CMD_ERROR;
goto end;
}
if (mm_dmp_add_cmd(mm_wka, cmd, mount_info->cmi_dm,
MM_DMP_ATTACH) == NULL) {
mms_trace(MMS_ERR,
"error adding dmp attach");
mm_system_error(cmd,
"error adding dmp attach");
goto reset_states;
}
cmd->cmd_state = 7;
return (MM_DISPATCH_DEPEND);
} else if (cmd->cmd_state == 7) {
PGresult *side;
PGresult *slot;
PGresult *mount_log;
PGresult *results;
int priv_no_vol = 0;
char *side_name = NULL;
char *slot_name = NULL;
char *slot_pcl = NULL;
/* DM_identify tester state */
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
mms_trace(MMS_DEVP, "mmp_mount-> DMP attach error");
/* Reset drive and cartridge */
/* return error to client */
mount_info->cmi_reset_states = 1;
mount_info->cmi_need_clear = 1;
/* DM is reserved, release the DM */
if (dmp_release = mm_dmp_add_cmd(mm_wka,
cmd, mount_info->cmi_dm,
MM_DMP_RELEASE)) {
/* run withtout parent */
mm_remove_all_depend(dmp_release);
}
/* write error message */
response_message =
mm_ret_response_msg(cmd);
mm_response_error(cmd,
ECLASS_SUBOP,
"EDMPATTACH",
5054,
"cartridge",
mount_info->cmi_cartridge,
"drive",
mount_info->cmi_drive,
"msg_rsp",
response_message,
MESS_END);
free(response_message);
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn,
cmd->cmd_buf);
rc = MM_CMD_ERROR;
goto end;
}
rc = mm_db_exec(HERE, db,
"select * from \"MOUNTPHYSICAL\" "\
"where \"CartridgeID\" = '%s';",
mount_info->cmi_cartridge);
if (rc != MM_DB_DATA) {
mms_trace(MMS_ERR, "Exec returned with no Data");
mm_sql_db_err_rsp_new(cmd, db);
goto reset_states;
}
mount_log = db->mm_db_results;
rows = PQntuples(mount_log);
mm_clear_db(&mount_log);
/* attach command has finished, add an indentify */
/* insert row into MOUNTLOGICAL */
rc = mm_db_exec(HERE, db,
"select \"VolumeName\", "
"\"PartitionName\", \"SideName\" "
"from \"VOLUME\" where \"CartridgeID\" = '%s'"
"and \"ApplicationName\" = '%s';",
mount_info->cmi_cartridge,
conn->cci_client);
if (rc != MM_DB_DATA) {
mm_sql_db_err_rsp_new(cmd, db);
goto reset_states;
}
results = db->mm_db_results;
if ((PQntuples(results) == 0) &&
(cmd->wka_ptr->wka_privilege != MM_PRIV_STANDARD)) {
/* Priv app doesn't have a volume */
rc = mm_db_exec(HERE, db,
"select \"VolumeName\", "
"\"PartitionName\", \"SideName\", "
"\"ApplicationName\" "
"from \"VOLUME\" where \"CartridgeID\" = '%s';",
mount_info->cmi_cartridge);
priv_no_vol = 1;
mm_clear_db(&results);
results = db->mm_db_results;
}
rc = mm_db_exec(HERE, db,
"select \"SideName\" from " \
"\"SIDE\" where \"CartridgeID\" = '%s';",
mount_info->cmi_cartridge);
if (rc != MM_DB_DATA) {
mm_sql_db_err_rsp_new(cmd, db);
mm_clear_db(&results);
goto reset_states;
}
side = db->mm_db_results;
if (PQntuples(side) == 0) {
mms_trace(MMS_DEVP,
"missing SIDE obj for %s",
mount_info->cmi_cartridge);
mm_system_error(cmd,
"cartridge missing SIDE obj");
mm_clear_db(&results);
mm_clear_db(&side);
goto reset_states;
}
side_name = PQgetvalue(side, 0, 0);
rc = mm_db_exec(HERE, db,
"select \"SlotName\", "\
"\"CartridgePCL\" from \"SLOT\" "\
"where \"CartridgeID\" = '%s';",
mount_info->cmi_cartridge);
if (rc != MM_DB_DATA) {
mm_sql_db_err_rsp_new(cmd, db);
mm_clear_db(&results);
mm_clear_db(&side);
goto reset_states;
}
slot = db->mm_db_results;
if (PQntuples(slot) == 0) {
mms_trace(MMS_DEVP,
"missing SLOT obj for %s",
mount_info->cmi_cartridge);
mm_system_error(cmd,
"cartridge missing SLOT obj");
mm_clear_db(&results);
mm_clear_db(&side);
mm_clear_db(&slot);
goto reset_states;
}
slot_name = PQgetvalue(slot, 0, 0);
slot_pcl = PQgetvalue(slot, 0, 1);
if (rows == 0) {
if (priv_no_vol) {
rc = mm_db_exec(HERE, db,
"insert into \"MOUNTLOGICAL\" "\
"(\"ApplicationName\", \"VolumeName\", "\
"\"PartitionName\", \"SideName\", "\
"\"CartridgeID\", \"DriveName\", "\
"\"DMName\", \"DMCapabilityName\", "\
"\"MountLogicalHandle\", "\
"\"MountLogicalTimeWhenMounted\") "\
"values ('%s', '%s', '%s', '%s', "\
"'%s', '%s', '%s', '%s', '%s', now());",
PQgetvalue(results, 0, 3),
PQgetvalue(results, 0, 0),
PQgetvalue(results, 0, 1),
PQgetvalue(results, 0, 2),
mount_info->cmi_cartridge,
mount_info->cmi_drive,
mount_info->cmi_dm,
mount_info->cmi_capability,
mount_info->cmi_handle);
} else {
rc = mm_db_exec(HERE, db,
"insert into \"MOUNTLOGICAL\" "
"(\"ApplicationName\", \"VolumeName\", "
"\"PartitionName\", \"SideName\", "
"\"CartridgeID\", \"DriveName\", "
"\"DMName\", \"DMCapabilityName\", "
"\"MountLogicalHandle\", "
"\"MountLogicalTimeWhenMounted\") "
"values ('%s', '%s', '%s', '%s', "
"'%s', '%s', '%s', '%s', '%s', now());",
conn->cci_client,
PQgetvalue(results, 0, 0),
PQgetvalue(results, 0, 1),
PQgetvalue(results, 0, 2),
mount_info->cmi_cartridge,
mount_info->cmi_drive,
mount_info->cmi_dm,
mount_info->cmi_capability,
mount_info->cmi_handle);
}
if (rc != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_mount_cmd_func: "
"error inserting MOUNTLOGICAL");
}
if (mm_db_exec(HERE, db,
"insert into \"MOUNTPHYSICAL\" "
"(\"ApplicationName\",\"DriveName\", "
"\"LibraryName\", "
"\"CartridgeID\", \"CartridgePCL\", "
"\"SideName\", "
"\"SlotName\", "
"\"MountPhysicalTimeWhenMounted\", "
"\"SessionID\") "
"values('%s', '%s', '%s', '%s', "
"'%s', '%s', '%s', now(), '%s');",
conn->cci_client,
mount_info->cmi_drive,
mount_info->cmi_library,
mount_info->cmi_cartridge,
slot_pcl,
side_name,
slot_name,
mm_wka->session_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_mount_cmd_func: "
"error inserting MOUNTPHYSICAL");
}
} else {
if (mm_db_exec(HERE, db,
"delete from \"MOUNTLOGICAL\" "\
"where \"CartridgeID\" = '%s';",
mount_info->cmi_cartridge) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_mount_cmd_func: "
"error deleting MOUNTLOGICAL");
}
rc = mm_db_exec(HERE, db,
"insert into \"MOUNTLOGICAL\" "\
"(\"ApplicationName\", \"VolumeName\", "\
"\"PartitionName\", \"SideName\", "\
"\"CartridgeID\", \"DriveName\", "\
"\"DMName\", \"DMCapabilityName\", "\
"\"MountLogicalHandle\", "\
"\"MountLogicalTimeWhenMounted\") "\
"values ('%s', '%s', '%s', '%s', "\
"'%s', '%s', '%s', '%s', '%s', now());",
conn->cci_client,
PQgetvalue(results, 0, 0),
PQgetvalue(results, 0, 1),
PQgetvalue(results, 0, 2),
mount_info->cmi_cartridge,
mount_info->cmi_drive,
mount_info->cmi_dm,
mount_info->cmi_capability,
mount_info->cmi_handle);
if (rc != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_mount_cmd_func: "
"error inserting MOUNTLOGICAL");
}
}
mm_clear_db(&results);
mm_clear_db(&side);
mm_clear_db(&slot);
if (mm_dmp_add_cmd(mm_wka, cmd, mount_info->cmi_dm,
MM_DMP_IDENTIFY) == NULL) {
mms_trace(MMS_ERR,
"error adding dmp identify");
mm_system_error(cmd,
"error adding dmp identify");
goto reset_states;
}
cmd->cmd_state = 8;
return (MM_DISPATCH_DEPEND);
} else if (cmd->cmd_state == 8) {
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
mms_trace(MMS_DEVP, "mmp_mount-> DMP identify error");
/* Reset drive and cartridge */
/* return error to client */
mount_info->cmi_reset_states = 1;
mount_info->cmi_need_clear = 1;
/* DM is reserved, release the DM */
if (dmp_release = mm_dmp_add_cmd(mm_wka,
cmd, mount_info->cmi_dm,
MM_DMP_RELEASE)) {
/* run withtout parent */
mm_remove_all_depend(dmp_release);
}
goto lm_dm_error;
}
/* The command is finished so generate a report */
/* Remove the TASK objs */
if (mm_db_exec(HERE, db, "delete from \"TASKCARTRIDGE\""
"where \"TaskID\" = '%s';",
cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_mount_cmd_func: "
"db error deleting TASKCARTRIDGE");
}
if (mm_db_exec(HERE, db, "delete from \"TASKDRIVE\" "
"where \"TaskID\" = '%s';", cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_mount_cmd_func: "
"db error deleting TASKDRIVE");
}
if (mm_db_exec(HERE, db, "delete from \"TASKLIBRARY\" "
"where \"TaskID\" = '%s';", cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_mount_cmd_func: "
"db error deleting TASKLIBRARY");
}
if (mm_db_exec(HERE, db, "delete from \"TASK\" "
"where \"TaskID\" = '%s';", cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_mount_cmd_func: "
"db error deleting TASK");
}
/*
* Report clause.
*/
cmd->cmd_remove = 1;
mm_path_match_report(cmd, db);
mm_send_response(mm_wka->mm_wka_conn, cmd);
mms_trace(MMS_INFO, "Tape Successfully Mounted");
rc = MM_CMD_DONE;
goto end;
}
cmd->cmd_remove = 1;
rc = MM_CMD_ERROR;
goto end;
reset_states:
mount_info->cmi_reset_states = 1;
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
return (MM_CMD_ERROR);
no_mem:
MM_ABORT_NO_MEM();
rc = MM_CMD_ERROR;
goto end;
not_found:
mm_response_error(cmd,
ECLASS_LANGUAGE,
ENOTFOUND,
5062,
MESS_END);
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
rc = MM_CMD_ERROR;
goto end;
lm_dm_error:
response_message =
mm_ret_response_msg(cmd);
mm_response_error(cmd,
ECLASS_SUBOP,
ELMDMCOMMUNICATION,
5055,
"msg_rsp", response_message,
MESS_END);
free(response_message);
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
/* Clear the Drive */
if (mount_info->cmi_drive != NULL) {
mount_info->cmi_need_clear = 1;
}
rc = MM_CMD_ERROR;
goto end;
db_error:
mm_sql_db_err_rsp_new(cmd, db);
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn,
cmd->cmd_buf);
rc = MM_CMD_ERROR;
goto end;
end:
return (rc);
}
int
mm_delay_unmount_cmd_func(mm_wka_t *mm_wka, mm_command_t *cmd)
{
time_t tm;
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
mm_db_t *db = &mm_wka->mm_data->mm_db;
char *response_message = NULL;
mms_trace(MMS_DEVP, "mm_delay_unmount_cmd_func %s",
cmd->cmd_mount_info.cmi_drive);
if (cmd->cmd_state == 0) {
(void) time(&tm);
if (tm < mount_info->unload_tm) {
mms_trace(MMS_DEVP,
"wait longer for this unload");
return (MM_DISPATCH_DEPEND);
}
if (mount_info->cui_skip_unload) {
mms_trace(MMS_DEVP,
"procced with unload, "
"but skip the DM unload command");
return (MM_CMD_DONE);
}
cmd->cmd_state = 1;
mms_trace(MMS_DEVP,
"proceed with DM unload command");
}
if (cmd->cmd_state == 1) {
if (mm_dmp_add_cmd(mm_wka, cmd, mount_info->cmi_dm,
MM_DMP_UNLOAD) == NULL) {
mms_trace(MMS_ERR,
"mm_delay_unmount_cmd_func: "
"error adding dmp unload");
return (MM_CMD_ERROR);
}
cmd->cmd_state = 2;
return (MM_DISPATCH_DEPEND);
}
if (cmd->cmd_state == 2) {
mm_command_t *lmp_umnt_cmd;
mm_wka_t *lm_wka;
uuid_text_t new_task;
char *cart_pcl;
char *side_name;
/*
* Unload has returned
* check error, update states
*/
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
mms_trace(MMS_DEVP, "delay unmount-> DMP unload error");
response_message = mm_ret_response_msg(cmd);
mm_response_error(cmd,
ECLASS_SUBOP,
ELMDMCOMMUNICATION,
5055,
"msg_rsp", response_message,
MESS_END);
free(response_message);
response_message = NULL;
}
/*
* Cartridge pcl and side name
*/
if ((cart_pcl = mm_get_cart_pcl(cmd,
cmd->cmd_mount_info.cmi_cartridge, db)) == NULL) {
cmd->cmd_remove = 1;
mms_trace(MMS_ERR,
"mm_get_cart_pcl error");
return (MM_CMD_ERROR);
}
mm_set_mount_info_pcl(cart_pcl,
mount_info);
/* TODO side name needs to be generated in candidate query */
if ((side_name = cmd->cmd_mount_info.cmi_side_name) == NULL) {
side_name = "side 1";
}
/*
* LMP unmount command
*/
lm_wka = mm_library_lm_wka(cmd->wka_ptr->mm_data,
cmd->cmd_mount_info.cmi_library, NULL);
if ((lmp_umnt_cmd = mm_alloc_cmd(lm_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,
cart_pcl, cart_pcl, side_name,
cmd->cmd_mount_info.cmi_drive,
cart_pcl, cart_pcl, side_name);
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");
cmd->cmd_state = 3;
pthread_mutex_lock(&mm_wka->mm_data->mm_queue_mutex);
mms_list_insert_tail(&mm_wka->mm_data->mm_cmd_queue,
lmp_umnt_cmd);
pthread_mutex_unlock(&mm_wka->mm_data->mm_queue_mutex);
free(cart_pcl);
return (MM_DISPATCH_DEPEND);
}
if (cmd->cmd_state == 3) {
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
mms_trace(MMS_ERR, "LMP unmount error, "
"scan both drive and slot");
/* Clear depend error flags */
MM_UNSET_FLAG(cmd->cmd_flags,
MM_CMD_DEPEND_ERROR);
/* 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 = 4;
return (MM_DISPATCH_DEPEND);
}
mms_trace(MMS_INFO, "Tape Unmounted Successfully");
/*
* Don't reset the soft state
* "\"DriveStateSoft\" = 'ready',"
*/
if (mm_db_exec(HERE, db, "update \"DRIVE\" set "
"\"DMName\" = '',"
"\"DriveStateHard\" = 'unloaded' where "
"\"DriveName\" = '%s';",
cmd->cmd_mount_info.cmi_drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_delay_unmount_cmd_func: "
"db error updating DriveStateHard");
}
/* Don't update the cartridge soft state */
/* The unload may be part of a mount sequence */
if (mm_has_depend(cmd)) {
mm_command_t *cur_depend = NULL;
mms_list_foreach(&cmd->cmd_depend_list, cur_depend) {
if (cur_depend->cmd_func ==
mm_delay_unmount_cmd_func) {
mms_trace(MMS_DEVP,
"this delay unmount has "
"delay unmount as parent,"
" set parent ready for dispatch");
mm_set_unload_dispatch(cur_depend,
NULL);
}
}
return (MM_DEPEND_DONE);
}
return (MM_CMD_DONE);
}
if (cmd->cmd_state == 4) {
/* This is state after lmp scan of drive */
/* send a scan of the cartridge now */
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
mms_trace(MMS_ERR, "error in LMP drive scan, try"
"slot scan anyways");
/* Clear depend error flags */
MM_UNSET_FLAG(cmd->cmd_flags,
MM_CMD_DEPEND_ERROR);
}
mms_trace(MMS_DEVP, "drive scan done, scan slot");
/* 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 = 5;
return (MM_DISPATCH_DEPEND);
}
if (cmd->cmd_state == 5) {
/* cartridge scan returned , return cmd done */
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
mms_trace(MMS_ERR, "error in LMP slot scan");
}
mms_trace(MMS_DEVP, "slot scan done");
/* Don't update the cartridge soft state */
/* The unload may be part of a mount sequence */
if (mm_has_depend(cmd)) {
mm_command_t *cur_depend = NULL;
mms_list_foreach(&cmd->cmd_depend_list, cur_depend) {
if (cur_depend->cmd_func ==
mm_delay_unmount_cmd_func) {
mms_trace(MMS_DEVP,
"this delay unmount has "
"delay unmount as parent,"
" set parent ready for dispatch");
mm_set_unload_dispatch(cur_depend,
NULL);
}
}
return (MM_DEPEND_DONE);
}
return (MM_CMD_DONE);
}
mms_trace(MMS_ERR,
"mm_delay_unmount_cmd_func: unknown command state");
return (MM_CMD_ERROR);
}
int
mm_schedule_unload(mm_wka_t *mm_wka, mm_command_t *cmd) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
mm_data_t *mm_data = mm_wka->mm_data;
mm_db_t *db = &mm_wka->mm_data->mm_db;
mm_command_t *unmount_cmd;
mm_wka_t *lm_wka;
uuid_text_t uuid;
/* Time releated */
char cur_date[100];
char unload_date[100];
time_t tm;
struct tm cur_time;
struct tm unload_time;
/* allocate the unmount command */
lm_wka = NULL;
lm_wka = mm_library_lm_wka(cmd->wka_ptr->mm_data,
cmd->cmd_mount_info.cmi_library, NULL);
if ((unmount_cmd = mm_alloc_cmd(lm_wka)) == NULL) {
mms_trace(MMS_ERR,
"Unable to malloc mm_command_t: %s",
strerror(errno));
return (1);
}
mm_get_uuid(uuid);
unmount_cmd->cmd_root = NULL;
unmount_cmd->cmd_task = NULL;
unmount_cmd->cmd_task = strdup(uuid);
unmount_cmd->cmd_func = mm_delay_unmount_cmd_func;
unmount_cmd->cmd_name = strdup("delay unmount");
/* Copy over the mount info to the new command */
if (mount_info->cmi_cartridge != NULL)
unmount_cmd->cmd_mount_info.cmi_cartridge =
strdup(mount_info->cmi_cartridge);
if (mount_info->cmi_drive != NULL)
unmount_cmd->cmd_mount_info.cmi_drive =
strdup(mount_info->cmi_drive);
if (mount_info->cmi_side_name != NULL)
unmount_cmd->cmd_mount_info.cmi_side_name =
strdup(mount_info->cmi_side_name);
if (mount_info->cmi_library != NULL)
unmount_cmd->cmd_mount_info.cmi_library =
strdup(mount_info->cmi_library);
if (mount_info->cmi_dm != NULL)
unmount_cmd->cmd_mount_info.cmi_dm =
strdup(mount_info->cmi_dm);
unmount_cmd->cmd_mount_info.cui_skip_unload =
mount_info->cui_skip_unload;
/* Set up timer */
if (mm_db_exec(HERE, db,
"select \"DriveGroupUnloadTime\" from "
"\"DRIVEGROUP\",\"DRIVE\" where "
"\"DRIVE\".\"DriveGroupName\" = "
"\"DRIVEGROUP\".\"DriveGroupName\" and "
"\"DRIVE\".\"DriveName\" = '%s';",
mount_info->cmi_drive) != MM_DB_DATA) {
mms_trace(MMS_ERR, "Exec returned with no Data");
return (1);
}
if (PQntuples(db->mm_db_results) != 1) {
mms_trace(MMS_ERR, "Exec rows != 1");
mm_clear_db(&db->mm_db_results);
return (1);
}
/* set the time to unload */
/* Get the delay time, get the current time */
(void) time(&tm);
mms_trace(MMS_DEVP, "Current tm is %d", tm);
(void) localtime_r(&tm, &cur_time);
(void) strftime(cur_date, 100, "%Y/%m/%d %H:%M:%S", &cur_time);
/* unload time is in min, so mult by 60 for sec */
tm = tm + 60*atoi(PQgetvalue(db->mm_db_results, 0, 0));
unmount_cmd->cmd_mount_info.unload_tm = tm;
mms_trace(MMS_DEVP, "Unload tm is %d", tm);
(void) localtime_r(&tm, &unload_time);
(void) strftime(unload_date, 100, "%Y/%m/%d %H:%M:%S", &unload_time);
mms_trace(MMS_DEVP,
"Current time is %s, delay time is %s mins, unload at %s",
cur_date, PQgetvalue(db->mm_db_results, 0, 0), unload_date);
pthread_mutex_lock(&mm_data->
mm_queue_mutex);
mms_list_insert_tail(&mm_data->mm_cmd_queue, unmount_cmd);
pthread_mutex_unlock(&mm_data->
mm_queue_mutex);
mm_clear_db(&db->mm_db_results);
return (0);
}
int
mm_parse_unmount_cmd(mm_wka_t *mm_wka, mm_command_t *cmd) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
mms_par_node_t *arg;
mms_par_node_t *value;
mms_par_node_t *work = NULL;
mms_trace(MMS_DEVP, "mm_parse_unmount_cmd");
mount_info->cmi_operation = MM_UNMOUNT;
/* Get the type */
mms_trace(MMS_DEVP, "type");
MMS_PN_LOOKUP(arg, cmd->cmd_root, "type",
MMS_PN_CLAUSE, NULL);
MMS_PN_LOOKUP(value, arg, NULL, MMS_PN_KEYWORD, NULL);
if (strcmp(value->pn_string, "SIDE") == 0) {
mount_info->cmi_type = MM_SIDE;
} else if (strcmp(value->pn_string, "PARTITION") == 0) {
mount_info->cmi_type = MM_PARTITION;
} else if (strcmp(value->pn_string, "VOLUME") == 0) {
mount_info->cmi_type = MM_VOLUME;
}
mms_trace(MMS_DEVP, "type %s", value->pn_string);
if (mms_pn_lookup(cmd->cmd_root, "physicalunmount",
MMS_PN_KEYWORD, NULL)) {
mount_info->cui_physical = 1;
}
mms_trace(MMS_DEVP, "physicalunmount %d",
mount_info->cui_physical);
/* signature optional */
if (arg = mms_pn_lookup(cmd->cmd_root, "signature",
MMS_PN_CLAUSE, NULL)) {
value = mms_pn_lookup(arg, NULL, MMS_PN_KEYWORD,
NULL);
if (value &&
strcmp(value->pn_string, "CLEAN") == 0) {
mount_info->cui_signature_clean = 1;
mms_trace(MMS_DEVP, "signature clean");
} else {
work = NULL;
MMS_PN_LOOKUP(value, arg, NULL,
MMS_PN_STRING, &work);
mount_info->cui_signature_type =
strdup(value->pn_string);
MMS_PN_LOOKUP(value, arg, NULL,
MMS_PN_STRING, &work);
mount_info->cui_signature =
strdup(value->pn_string);
mms_trace(MMS_DEVP, "signature %s %s",
mount_info->cui_signature_type,
mount_info->cui_signature);
}
} else {
/* default signature */
mount_info->cui_signature_clean = 1;
mms_trace(MMS_DEVP, "signature defaults to clean");
}
return (MM_CMD_DONE);
not_found:
mm_response_error(cmd,
ECLASS_LANGUAGE,
ENOTFOUND,
5062,
MESS_END);
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
return (MM_CMD_ERROR);
no_mem:
MM_ABORT_NO_MEM();
return (MM_CMD_ERROR);
}
PGresult*
mm_unmount_cart_results(mm_wka_t *mm_wka,
mm_command_t *cmd, mm_db_t *db) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
char *tmp_buf = NULL;
cci_t *conn = &mm_wka->wka_conn;
char *app_name = conn->cci_client;
char *type = NULL;
int i;
mm_clear_source(cmd);
mm_clear_dest(cmd);
mm_clear_const(cmd);
switch (mount_info->cmi_type) {
case MM_SIDE:
type = mms_strapp(type, MM_SIDE_STRING);
break;
case MM_PARTITION:
type = mms_strapp(type, MM_PARTITION_STRING);
break;
case MM_VOLUME:
type = mms_strapp(type, MM_VOLUME_STRING);
break;
}
/* Do drive/cart/lib selection using path matching */
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);
}
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);
}
if (cmd->wka_ptr->wka_privilege == MM_PRIV_STANDARD) {
/* add CARTRIDGEGROUPAPPLICATION constraint */
(void) mm_add_to_dest(cmd,
"CARTRIDGEGROUPAPPLICATION");
if (tmp_buf)
free(tmp_buf);
tmp_buf = NULL;
tmp_buf = mms_strapp(tmp_buf,
"\"CARTRIDGEGROUPAPPLICATION\"."
"\"ApplicationName\" = '%s'",
app_name);
(void) mm_add_to_const(cmd, tmp_buf);
if (tmp_buf)
free(tmp_buf);
tmp_buf = NULL;
}
/* Constrain to only cartridges mounted by this session */
/* Maybe a forced unmount will not use this constraint */
(void) mm_add_to_dest(cmd,
"SESSION");
if (tmp_buf)
free(tmp_buf);
tmp_buf = NULL;
tmp_buf = mms_strapp(tmp_buf,
"\"SESSION\"."
"\"ConnectionID\" = '%s'",
conn->cci_uuid);
(void) mm_add_to_const(cmd, tmp_buf);
if (tmp_buf)
free(tmp_buf);
tmp_buf = NULL;
/* Add MOUNTPHYSICAL constraint */
/* Maybe a forced unmount will not use this constraint */
(void) mm_add_to_dest(cmd,
"MOUNTPHYSICAL");
if (tmp_buf)
free(tmp_buf);
tmp_buf = NULL;
tmp_buf = mms_strapp(tmp_buf,
"(\"MOUNTPHYSICAL\".\"CartridgeID\" "
"= \"%s\".\"CartridgeID\")", type);
(void) mm_add_to_const(cmd, tmp_buf);
if (tmp_buf)
free(tmp_buf);
tmp_buf = NULL;
/* Make tmp_buf and set source */
(void) mm_add_to_source(cmd, type);
tmp_buf = mms_strapp(tmp_buf,
"select \"%s\"."
"\"CartridgeID\" from\n ", type);
if (type)
free(type);
type = NULL;
SQL_CHK_LEN(&cmd->cmd_buf, NULL,
&cmd->cmd_bufsize, strlen(tmp_buf) + 1);
strcpy(cmd->cmd_buf, tmp_buf);
if (tmp_buf)
free(tmp_buf);
tmp_buf = NULL;
if (mm_sql_from_where(cmd, db)) {
mms_trace(MMS_ERR,
"mm_unmount_cart_results: "
"db error creating helper functions");
return (NULL);
}
if (mm_db_exec(HERE, db, cmd->cmd_buf) != MM_DB_DATA) {
mm_sql_db_err_rsp_new(cmd, db);
return (NULL);
}
if (PQntuples(db->mm_db_results) == 0) {
/* no cartridge matches */
mms_trace(MMS_INFO,
"match statment in mount "
"didn't match any cartridge/volumes");
mm_response_error(cmd,
ECLASS_EXPLICIT, ENOMATCH,
5052,
MESS_END);
return (NULL);
}
tmp_buf = mms_strapp(tmp_buf,
"select distinct \"CartridgeID\","
"\"LibraryName\",\"CartridgeGroupPriority\","
"\"CartridgeNumberMounts\", "
"\"CartridgeTypeName\",\"CartridgePCL\", "
"\"CartridgeDriveOccupied\" "
"from ( "
"select \"CartridgeID\",\"LibraryName\", "
"\"CartridgeGroupPriority\","
"\"CartridgeNumberMounts\", "
"\"CartridgeTypeName\",\"CartridgePCL\", "
"\"CartridgeDriveOccupied\" "
"from \"CARTRIDGE\",\"CARTRIDGEGROUP\"");
for (i = 0; i < PQntuples(db->mm_db_results); i++) {
if (i == 0) {
tmp_buf = mms_strapp(tmp_buf, "where (");
} else {
tmp_buf = mms_strapp(tmp_buf, "or ");
}
tmp_buf = mms_strapp(tmp_buf, " (\"CartridgeID\" = '%s')",
PQgetvalue(db->mm_db_results, i, 0));
}
tmp_buf = mms_strapp(tmp_buf,
") and"
"(\"CARTRIDGEGROUP\".\"CartridgeGroupName\" "
"= \"CARTRIDGE\".\"CartridgeGroupName\")"
"order by \"CARTRIDGE\".\"CartridgeTimeMountedLast\""
") as foo order by \"CartridgeGroupPriority\";");
mm_clear_db(&db->mm_db_results);
if (mm_db_exec(HERE, db, tmp_buf) != MM_DB_DATA) {
if (tmp_buf)
free(tmp_buf);
tmp_buf = NULL;
mm_sql_db_err_rsp_new(cmd, db);
return (NULL);
}
if (tmp_buf)
free(tmp_buf);
tmp_buf = NULL;
return (db->mm_db_results);
no_mem:
MM_ABORT_NO_MEM();
return (NULL);
}
int
mm_unmount_ready(mm_wka_t *mm_wka, mm_command_t *cmd, mm_db_t *db) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
PGresult *cart_results;
int cart_rows;
int found_cart_drive = 0;
int found_ready_cart_drive = 0;
cmi_cart_list_t *cart = NULL;
cmi_drive_list_t *drive = NULL;
int rc;
/* Do drive/cart/lib selection using path matching */
if ((cart_results = mm_unmount_cart_results(mm_wka,
cmd, db)) == NULL) {
/* No carts or error */
return (MM_UNMOUNT_ERROR);
}
cart_rows = PQntuples(cart_results);
mms_trace(MMS_DEVP, "Number of Cartridges is %d", cart_rows);
if (cart_rows == 0) {
/* No Cartridge Matches Error */
mms_trace(MMS_INFO,
"match statment in mount "
"didn't match any cartridge/volumes");
mm_response_error(cmd,
ECLASS_EXPLICIT, ENOMATCH,
5052,
MESS_END);
mm_clear_db(&cart_results);
return (MM_UNMOUNT_ERROR);
}
/* Create the list objects for */
/* every cartridge/drive candidate */
if (mm_mount_init_candidates(cmd, cart_results,
db)) {
mms_trace(MMS_ERR,
"error initializing candidate lists");
/* err buf should be set by mm_mount_init */
/* so return and remove */
mm_clear_db(&cart_results);
return (MM_UNMOUNT_ERROR);
}
mms_trace(MMS_DEVP, "candidate list created, check availability ");
mm_clear_db(&cart_results);
/* Check the availability of the candidates */
if (mm_mount_check_candidates(mm_wka, cmd,
db)) {
mms_trace(MMS_ERR,
"error checking candidate lists");
mm_system_error(cmd,
"error checking candidate lists");
return (MM_UNMOUNT_ERROR);
}
mms_trace(MMS_DEVP, "done checking list");
/* Print mount information */
mm_print_mount_summary(mm_wka, cmd);
found_cart_drive = 0;
found_ready_cart_drive = 0;
mms_list_foreach(&mount_info->cmi_cart_list, cart) {
if (cart->cmi_cart_not_ready)
cart->cmi_remove_cart = 1;
mms_list_foreach(&cart->cmi_drive_list, drive) {
found_cart_drive = 1;
if ((cart->cmi_cart_not_ready == 0) &&
(drive->cmi_drive_not_ready == 0)) {
found_ready_cart_drive = 1;
}
if (drive->cmi_drive_not_ready)
drive->cmi_remove_drive = 1;
}
}
/* If there is a library or drive error */
/* the error buff has already been set */
if (found_cart_drive == 0) {
mms_trace(MMS_INFO,
"No candidate "
"cartridge/library/drive "
"combination found");
return (MM_UNMOUNT_ERROR);
}
if (found_ready_cart_drive == 0) {
mms_trace(MMS_INFO,
"candidate "
"cartridge/library/drive "
"combination found, but is not ready");
return (MM_UNMOUNT_NOT_READY);
}
/* There is a ready cart/drive */
/* we may have set some non ready for remove */
/* so call the clean func before contine */
mm_mount_clean_candidates(cmd);
cmd->cmd_state = 1;
rc = mm_set_immediate_unmount(cmd, db);
if (rc == MM_CMD_ERROR) {
mms_trace(MMS_ERR,
"error setting up immediate mount");
return (MM_UNMOUNT_ERROR);
}
mms_trace(MMS_DEVP,
"mount ready for dispatch");
return (MM_UNMOUNT_READY);
}
int
mm_unmount_cmd_func(mm_wka_t *mm_wka, mm_command_t *cmd)
{
mm_db_t *db = &mm_wka->mm_data->mm_db;
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
int rc;
char *response_message = NULL;
mms_trace(MMS_DEVP, "mm unmount state %d", cmd->cmd_state);
mm_print_unmount_state(cmd->cmd_state);
/* UM_CANDIDATE_SELECTION == 0 */
if (cmd->cmd_state == UM_CANDIDATE_SELECTION) {
mms_trace(MMS_INFO, "Processing Unmount Request...");
/*
* Generate Candidate Cartridge and Drive lists
* First parse and save the mount info
* then use SQL queries to gereate the lists
*/
if (mm_parse_unmount_cmd(mm_wka, cmd) == MM_CMD_ERROR) {
mms_trace(MMS_ERR,
"error parsing unmount command");
/* Error buf should already be set */
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
return (MM_CMD_ERROR);
}
mms_trace(MMS_DEVP, "done parsing unmount");
if (mm_set_tm_task(db, cmd) != MM_DB_OK) {
goto db_error;
}
mms_trace(MMS_DEVP,
"unmount will be passed to task manager");
return (MM_WORK_TODO);
} else if (cmd->cmd_state == UM_DM_DETACH) {
mms_trace(MMS_INFO, "Unmounting Tape...");
/*
* Add Detach command
*/
if (mm_dmp_add_cmd(mm_wka, cmd,
mount_info->cmi_dm,
MM_DMP_DETACH) == NULL) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"error adding dmp unload");
mm_system_error(cmd,
"error adding dmp unload");
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn,
cmd->cmd_buf);
return (MM_CMD_ERROR);
}
cmd->cmd_state = UM_DM_RELEASE;
return (MM_DISPATCH_DEPEND);
}
if (cmd->cmd_state == UM_DM_RELEASE) {
/*
* Detach has returned
* check error, update states
* Add release command
*/
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
mms_trace(MMS_DEVP, "mmp_unmount-> DMP detach error");
if ((cmd->cmd_response != NULL) &&
mm_errorcode_eq(cmd->cmd_response,
"DM_E_NOEXISTHANDLE")) {
/* DM doesn't know about the handle */
/* Continue with unmount regardless */
/* skip unload */
mms_trace(MMS_DEVP,
"DM doesn't know the handle, "
"skip DMP unload, "
"send LMP unmount");
mount_info->cui_skip_unload = 1;
/* Clear depend error flags */
MM_UNSET_FLAG(cmd->cmd_flags,
MM_CMD_DEPEND_ERROR);
} else {
mount_info->cmi_reset_states = 1;
mount_info->cmi_need_clear = 1;
response_message =
mm_ret_response_msg(cmd);
mm_response_error(cmd,
ECLASS_SUBOP,
ELMDMCOMMUNICATION,
5055,
"msg_rsp", response_message,
MESS_END);
free(response_message);
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
rc = MM_CMD_ERROR;
goto end;
}
}
if (mm_db_exec(HERE, db, "delete from \"MOUNTLOGICAL\" " \
"where \"CartridgeID\" = '%s';",
mount_info->cmi_cartridge) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"db error deleteing MOUNTLOGICAL");
}
if (mm_db_exec(HERE, db, "delete from \"STALEHANDLE\" "\
"where \"CartridgeID\" = '%s';",
mount_info->cmi_cartridge) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"db error deleteing STALEHANDLE");
}
if (mm_dmp_add_cmd(mm_wka, cmd, mount_info->cmi_dm,
MM_DMP_RELEASE) == NULL) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"error adding dmp release");
mm_system_error(cmd,
"error adding dmp release");
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn,
cmd->cmd_buf);
return (MM_CMD_ERROR);
}
cmd->cmd_state = UM_SCHEDULE_UNLOAD;
return (MM_DISPATCH_DEPEND);
}
if (cmd->cmd_state == UM_SCHEDULE_UNLOAD) {
/*
* release command has returned
* check for errors, update states
*/
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
mms_trace(MMS_DEVP, "mmp_unmount-> DMP release error");
mount_info->cmi_reset_states = 1;
mount_info->cmi_need_clear = 1;
mm_response_error(cmd,
ECLASS_SUBOP,
ELMDMCOMMUNICATION,
5055,
"msg_rsp", mm_ret_response_msg(cmd),
MESS_END);
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
rc = MM_CMD_ERROR;
goto end;
}
if (mount_info->cui_physical) {
/* This is a physical unmount */
cmd->cmd_state = UM_LM_UNMOUNT;
if (mm_dmp_add_cmd(mm_wka, cmd, mount_info->cmi_dm,
MM_DMP_UNLOAD) == NULL) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"error adding dmp unload");
mm_system_error(cmd,
"error adding dmp unload");
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn,
cmd->cmd_buf);
return (MM_CMD_ERROR);
}
rc = MM_DISPATCH_DEPEND;
goto end;
}
/* Delayed unmount */
mms_trace(MMS_DEVP,
"DELAY UNLOAD NOW!!!!");
/* update drive and cartridge states */
if (mm_db_exec(HERE, db, "update \"DRIVE\" set "
"\"DriveStateSoft\" = 'ready',"
"\"DMName\" = ''"
" where "
"\"DriveName\" = '%s';",
cmd->cmd_mount_info.cmi_drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"db error updating DriveStateSoft");
}
if (mm_db_exec(HERE, db,
"update \"CARTRIDGE\" set \"CartridgeStatus\" "
"= 'available' where "
"\"CartridgeID\" = '%s';",
cmd->cmd_mount_info.cmi_cartridge) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"db error updating CartridgeStatus");
}
if (mm_db_exec(HERE, db, "delete from \"TASKCARTRIDGE\""
"where \"TaskID\" = '%s';", cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"db error deleting TASKCARTRIDGE");
}
if (mm_db_exec(HERE, db, "delete from \"TASKDRIVE\" "
"where \"TaskID\" = '%s';", cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"db error deleting TASKDRIVE");
}
if (mm_db_exec(HERE, db, "delete from \"TASKLIBRARY\" "
"where \"TaskID\" = '%s';", cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"db error deleting TASKLIBRARY");
}
if (mm_db_exec(HERE, db, "delete from \"TASK\" "
"where \"TaskID\" = '%s';", cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"db error deleting TASK");
}
if (mm_db_exec(HERE, db, "delete from \"MOUNTPHYSICAL\" "
"where \"CartridgeID\" = '%s';",
mount_info->cmi_cartridge) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"db error deleting MOUNTPHYSICAL");
}
if (mm_schedule_unload(mm_wka, cmd)) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"error scheduling unload");
}
/* Send success for the unmount */
mm_path_match_report(cmd, db);
cmd->cmd_remove = 1;
mm_send_response(mm_wka->mm_wka_conn, cmd);
rc = MM_DISPATCH_AGAIN;
goto end;
}
if (cmd->cmd_state == UM_LM_UNMOUNT) {
mm_command_t *lmp_umnt_cmd;
mm_wka_t *lm_wka;
uuid_text_t new_task;
char *cart_pcl;
char *side_name;
/*
* Unload has returned
* check error, update states
* Add release command
*/
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
mount_info->cmi_reset_states = 1;
mount_info->cmi_need_clear = 1;
mms_trace(MMS_DEVP, "mmp_unmount-> DMP unload error");
response_message =
mm_ret_response_msg(cmd);
mm_response_error(cmd,
ECLASS_SUBOP,
ELMDMCOMMUNICATION,
5055,
"msg_rsp", response_message,
MESS_END);
free(response_message);
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
rc = MM_CMD_ERROR;
goto end;
}
/*
* Cartridge pcl and side name
*/
if ((cart_pcl = mm_get_cart_pcl(cmd,
cmd->cmd_mount_info.cmi_cartridge, db)) == NULL) {
cmd->cmd_remove = 1;
mms_trace(MMS_ERR,
"mm_get_cart_pcl error");
return (MM_CMD_ERROR);
}
/* TODO side name needs to be generated in candidate query */
if ((side_name = cmd->cmd_mount_info.cmi_side_name) == NULL) {
side_name = "side 1";
}
/*
* LMP unmount command
*/
lm_wka = mm_library_lm_wka(cmd->wka_ptr->mm_data,
cmd->cmd_mount_info.cmi_library, NULL);
if ((lmp_umnt_cmd = mm_alloc_cmd(lm_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,
cart_pcl, cart_pcl, side_name,
cmd->cmd_mount_info.cmi_drive,
cart_pcl, cart_pcl, side_name);
mm_set_mount_info_drive(cmd->cmd_mount_info.cmi_drive,
&lmp_umnt_cmd->cmd_mount_info);
mm_set_mount_info_pcl(cart_pcl,
&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");
cmd->cmd_state = UM_FINAL;
pthread_mutex_lock(&mm_wka->mm_data->mm_queue_mutex);
mms_list_insert_tail(&mm_wka->mm_data->
mm_cmd_queue, lmp_umnt_cmd);
pthread_mutex_unlock(&mm_wka->mm_data->mm_queue_mutex);
free(cart_pcl);
return (MM_DISPATCH_DEPEND);
} else if (cmd->cmd_state == UM_FINAL) {
if (cmd->cmd_flags & MM_CMD_DEPEND_ERROR) {
mms_trace(MMS_DEVP, "lm unmount failed");
mount_info->cmi_reset_states = 1;
mount_info->cmi_need_clear = 1;
response_message =
mm_ret_response_msg(cmd);
mm_response_error(cmd,
ECLASS_SUBOP,
ELMDMCOMMUNICATION,
5055,
"msg_rsp", response_message,
MESS_END);
free(response_message);
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
rc = MM_CMD_ERROR;
goto end;
}
/*
* TEMPORARY update drive states remove TASK objs
*/
/* If cmd_depend is set this is part of a begin-end group */
/* so do not reset the drive state */
if (mm_has_depend(cmd) == 0) {
if (mm_db_exec(HERE, db, "update \"DRIVE\" set "
"\"DriveStateSoft\" = 'ready',"
"\"DMName\" = '',"
"\"DriveStateHard\" = 'unloaded' where "
"\"DriveName\" = '%s';",
cmd->cmd_mount_info.cmi_drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"db error updating DRIVE");
}
} else {
if (mm_db_exec(HERE, db, "update \"DRIVE\" set "
"\"DMName\" = '',"
"\"DriveStateHard\" = 'unloaded' where "
"\"DriveName\" = '%s';",
cmd->cmd_mount_info.cmi_drive) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"db error updating DRIVE");
}
}
if (mm_db_exec(HERE, db,
"update \"CARTRIDGE\" set \"CartridgeStatus\" "
"= 'available' where "
"\"CartridgeID\" = '%s';",
cmd->cmd_mount_info.cmi_cartridge) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"db error updating CartridgeStatus");
}
if (mm_db_exec(HERE, db, "delete from \"TASKCARTRIDGE\""
"where \"TaskID\" = '%s';", cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"db error deleting TASKCARTRIDGE");
}
if (mm_db_exec(HERE, db, "delete from \"TASKDRIVE\" "
"where \"TaskID\" = '%s';", cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"db error deleting TASKDRIVE");
}
if (mm_db_exec(HERE, db, "delete from \"TASKLIBRARY\" "
"where \"TaskID\" = '%s';", cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"db error deleting TASKLIBRARY");
}
if (mm_db_exec(HERE, db, "delete from \"TASK\" "
"where \"TaskID\" = '%s';", cmd->cmd_uuid) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"db error deleting TASK");
}
if (mm_db_exec(HERE, db, "delete from \"MOUNTPHYSICAL\" "
"where \"CartridgeID\" = '%s';",
mount_info->cmi_cartridge) != MM_DB_OK) {
mms_trace(MMS_ERR,
"mm_unmount_cmd_func: "
"db error deleting MOUNTPHYSICAL");
}
/*
* Report clause.
*/
mm_path_match_report(cmd, db);
cmd->cmd_remove = 1;
mm_send_response(mm_wka->mm_wka_conn, cmd);
mms_trace(MMS_INFO, "Tape Unmounted Successfully");
if (mm_has_depend(cmd)) {
mm_command_t *cur_depend = NULL;
mms_list_foreach(&cmd->cmd_depend_list, cur_depend) {
if (cur_depend->cmd_func ==
mm_delay_unmount_cmd_func) {
mms_trace(MMS_DEVP,
"this delay unmount has "
"delay unmount as parent,"
" set parent ready for dispatch");
mm_set_unload_dispatch(cur_depend,
NULL);
}
}
rc = MM_DEPEND_DONE;
goto end;
}
rc = MM_CMD_DONE;
goto end;
}
mms_trace(MMS_ERR, "Unknown state");
cmd->cmd_remove = 1;
rc = MM_CMD_ERROR;
goto end;
no_mem:
MM_ABORT_NO_MEM();
rc = MM_CMD_ERROR;
goto end;
not_found:
mm_response_error(cmd,
ECLASS_LANGUAGE,
ENOTFOUND,
5062,
MESS_END);
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
rc = MM_CMD_ERROR;
goto end;
db_error:
mm_sql_db_err_rsp_new(cmd, db);
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn,
cmd->cmd_buf);
rc = MM_CMD_ERROR;
goto end;
end:
return (rc);
}
int
mm_begin_cmd_func(mm_wka_t *mm_wka, mm_command_t *cmd)
{
mms_par_node_t *arg;
mms_par_node_t *value;
mm_db_t *db = &mm_wka->mm_data->mm_db;
mms_trace(MMS_DEVP, "sql trans begin cmd");
if (cmd->cmd_state == 0) {
mms_trace(MMS_DEVP, "when");
arg = mms_pn_lookup(cmd->cmd_root, "when",
MMS_PN_CLAUSE, NULL);
if (arg != NULL) {
MMS_PN_LOOKUP(value,
arg, NULL, MMS_PN_KEYWORD, NULL);
if (strcmp(value->pn_string, "blocking") == 0) {
mm_wka->wka_begin_end.be_mode =
ACCESS_MODE_BLOCKING;
} else {
mm_wka->wka_begin_end.be_mode =
ACCESS_MODE_IMMEDIATE;
}
} else {
/* when is optional and defaults to immediate */
mm_wka->wka_begin_end.be_mode = ACCESS_MODE_IMMEDIATE;
}
mms_trace(MMS_DEVP, "ready for mount unmount command group");
/* return MM_DISPATCH_DEPEND??? */
cmd->cmd_state = 1;
return (MM_DISPATCH_DEPEND);
}
if (cmd->cmd_state == 1) {
/* when End has been accepted, send success for begin */
/* Send success */
mm_path_match_report(cmd, db);
cmd->cmd_remove = 1;
mm_send_response(mm_wka->mm_wka_conn, cmd);
return (MM_DEPEND_DONE);
}
mms_trace(MMS_ERR,
"bad command state- begin command");
mm_system_error(cmd,
"bad command state- begin command");
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
mm_wka->wka_begin_end.be_active = B_FALSE;
cmd->cmd_remove = 1;
return (MM_CMD_ERROR);
no_mem:
MM_ABORT_NO_MEM();
return (MM_CMD_ERROR);
not_found:
mm_response_error(cmd,
ECLASS_LANGUAGE,
ENOTFOUND,
5062,
MESS_END);
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
return (MM_CMD_ERROR);
}
void
mm_mv_beginend(mm_command_t *begin, mm_command_t *end) {
/* begin end command list */
mm_command_t *cur_cmd;
mm_command_t *next_cmd;
/* Move beginend commands from begin to end */
for (cur_cmd = mms_list_head(&begin->cmd_beginend_list);
cur_cmd != NULL;
cur_cmd = next_cmd) {
next_cmd =
mms_list_next(&begin->cmd_beginend_list,
cur_cmd);
mms_list_remove(&begin->cmd_beginend_list,
cur_cmd);
mms_list_insert_tail(&end->cmd_beginend_list,
cur_cmd);
}
}
int
mm_be_parse_cmds(mm_command_t *cmd) {
mm_command_t *cur_cmd;
int cmd_count = 0;
mm_wka_t *mm_wka = cmd->wka_ptr;
cmd_count = 0;
mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) {
cmd_count ++;
mms_trace(MMS_DEVP,
"Begin-end cmd %d, %s",
cmd_count, cur_cmd->cmd_name);
if (cur_cmd->cmd_func == mm_mount_cmd_func) {
if (mm_parse_mount_cmd(cur_cmd->wka_ptr,
cur_cmd) == MM_CMD_ERROR) {
mms_trace(MMS_ERR,
"error parsing unmount command");
/* Error buf should already be set */
return (-1);
}
} else {
if (mm_parse_unmount_cmd(cur_cmd->wka_ptr,
cur_cmd) == MM_CMD_ERROR) {
mms_trace(MMS_ERR,
"error parsing unmount command");
/* Error buf should already be set */
return (-1);
}
}
if (mm_wka->wka_begin_end.be_mode == ACCESS_MODE_IMMEDIATE) {
cur_cmd->cmd_mount_info.cmi_when = MM_IMMEDIATE;
} else {
cur_cmd->cmd_mount_info.cmi_when = MM_BLOCKING;
}
}
return (cmd_count);
}
int
mm_end_cmd_func(mm_wka_t *mm_wka, mm_command_t *cmd)
{
mm_command_t *be_command = NULL;
int cmd_count;
mm_db_t *db = &mm_wka->mm_data->mm_db;
mms_trace(MMS_DEVP, "mm_end_cmd_func");
if (cmd->cmd_state == 0) {
be_command = cmd->cmd_begin_cmd;
if (be_command == NULL) {
mms_trace(MMS_ERR,
"couldn't find begin for this end");
mm_system_error(cmd,
"couldn't find begin for this end");
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
return (MM_CMD_ERROR);
}
/* Copy begin cmd list ptr */
/* set begin for dispatch */
/* as depend */
mm_add_depend(be_command, cmd);
mm_mv_beginend(be_command, cmd);
MM_SET_FLAG(be_command->cmd_flags,
MM_CMD_DISPATCHABLE);
cmd->cmd_state = 1;
return (MM_DISPATCH_DEPEND);
}
if (cmd->cmd_state == 1) {
/* Begin has returned success */
/* abort command group */
if (mms_pn_lookup(cmd->cmd_root, "abort",
MMS_PN_KEYWORD, NULL)) {
/* Cancel all the commands */
/* and return success for the abort */
mms_trace(MMS_DEVP, "begin-end abort");
mm_path_match_report(cmd, db);
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
tm_be_cancel_all(cmd);
return (MM_CMD_DONE);
}
if ((cmd_count = mm_be_parse_cmds(cmd)) == -1) {
/* Error parsing a command */
mm_system_error(cmd,
"error parsing mount/unmount "
"inside begin-end group");
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
return (MM_CMD_ERROR);
} else if (cmd_count == 0) {
/* No commands in this command group */
/* Send success ??? */
mm_path_match_report(cmd, db);
cmd->cmd_remove = 1;
mm_send_response(mm_wka->mm_wka_conn, cmd);
return (MM_CMD_DONE);
}
mms_trace(MMS_DEVP,
"done parsing %d commands for begin-end group",
cmd_count);
if (mm_set_tm_task(db, cmd) != MM_DB_OK) {
mm_sql_db_err_rsp_new(cmd, db);
cmd->cmd_remove = 1;
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
return (MM_CMD_ERROR);
}
cmd->cmd_state = 2;
mms_trace(MMS_DEVP,
"begin-end group will be passed to task manager");
return (MM_WORK_TODO);
}
if (cmd->cmd_state == 2) {
/* Task manager has dispatched this command */
/* Send success for end */
mms_trace(MMS_DEVP, "end command state 2");
cmd->cmd_remove = 1;
return (MM_CMD_DONE);
}
mms_trace(MMS_ERR,
"bad command state- end command");
mm_system_error(cmd,
"bad command state- end command");
mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf);
cmd->cmd_remove = 1;
return (MM_CMD_ERROR);
no_mem:
MM_ABORT_NO_MEM();
return (MM_CMD_ERROR);
}