1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 * 21 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 22 * Use is subject to license terms. 23 */ 24 25 26 #include <sys/types.h> 27 #include <mms_list.h> 28 #include <mms_parser.h> 29 #include <libpq-fe.h> 30 #include <string.h> 31 #include <stdlib.h> 32 #include <pthread.h> 33 #include <errno.h> 34 #include <syslog.h> 35 #include <mms_trace.h> 36 #include <mms_strapp.h> 37 #include "mm_db.h" 38 #include "mm.h" 39 #include "mm_util.h" 40 #include "mm_sql.h" 41 #include "mm_commands.h" 42 #include "mm_sql.h" 43 #include "mm_sql_impl.h" 44 #include "mm_task.h" 45 46 static char *_SrcFile = __FILE__; 47 48 #define MM_BE_ERROR 0 49 #define MM_BE_DISPATCH 1 50 #define MM_BE_BLOCKING 2 51 #define MM_BE_OK 3 52 53 cmi_drive_list_t * 54 tm_return_drive_ptr(char *drive, cmi_cart_list_t *cart) { 55 /* if drive is NULL return the 1st drive in the list */ 56 cmi_drive_list_t *cur_drive = NULL; 57 58 if (drive == NULL) { 59 cur_drive = mms_list_head(&cart->cmi_drive_list); 60 if (cur_drive == NULL) { 61 mms_trace(MMS_ERR, 62 "1st drive was NULL"); 63 } 64 return (cur_drive); 65 66 } 67 68 mms_list_foreach(&cart->cmi_drive_list, cur_drive) { 69 if (strcmp(cur_drive->cmi_drive_name, 70 drive) == 0) { 71 return (cur_drive); 72 } 73 } 74 return (NULL); 75 } 76 77 cmi_cart_list_t * 78 tm_return_cart_ptr(char *cart_id, cmd_mount_info_t *mount_info) { 79 cmi_cart_list_t *cur_cart; 80 mms_list_foreach(&mount_info->cmi_cart_list, cur_cart) { 81 if (strcmp(cur_cart->cmi_cart_id, 82 cart_id) == 0) { 83 return (cur_cart); 84 } 85 } 86 return (NULL); 87 } 88 89 90 char * 91 tm_return_dm_name(char *drive_name, char *host, mm_data_t *mm_data) { 92 /* Return the dm name for drive_name on host */ 93 mm_db_t *db = &mm_data->mm_db_tm; 94 char *dm_name = NULL; 95 if (mm_db_exec(HERE, db, 96 "select \"DMName\" from \"DM\" " 97 "where \"DM\".\"DriveName\" = '%s' and " 98 " pg_host_ident(\"DMTargetHost\") " 99 "= pg_host_ident('%s');", 100 drive_name, host) != MM_DB_DATA) { 101 mms_trace(MMS_ERR, 102 "db error, tm_return_dm_name"); 103 return (NULL); 104 } 105 if (PQntuples(db->mm_db_results) != 1) { 106 mms_trace(MMS_ERR, 107 "row num mismatch , tm_return_dm_name"); 108 return (NULL); 109 } 110 dm_name = mms_strapp(dm_name, PQgetvalue(db->mm_db_results, 0, 0)); 111 mm_clear_db(&db->mm_db_results); 112 return (dm_name); 113 } 114 115 int 116 tm_can_dispatch_mount(mm_command_t *cmd, mm_data_t *mm_data) 117 { 118 119 /* Use this function for both unmout and mounts */ 120 mm_db_t *db = &mm_data->mm_db_tm; 121 122 mm_wka_t *mm_wka = cmd->wka_ptr; 123 124 125 int rc; 126 127 mms_trace(MMS_DEVP, 128 "tm_can_dispatch_mount"); 129 130 rc = mm_mount_ready(mm_wka, cmd, db, 0); 131 switch (rc) { 132 133 case MM_MOUNT_ERROR: 134 /* Error code should be set */ 135 mms_trace(MMS_ERR, 136 "internal error, mm_mount_ready"); 137 cmd->cmd_remove = 1; 138 mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf); 139 return (0); 140 141 case MM_MOUNT_READY: 142 /* The mount is ready, mount_info should be set */ 143 /* continue to state 1 */ 144 cmd->cmd_state = 1; 145 mms_trace(MMS_DEVP, 146 "mount is ready to go, " 147 "continue to state 1"); 148 MM_SET_FLAG(cmd->cmd_flags, MM_CMD_DISPATCHABLE); 149 return (1); 150 151 case MM_MOUNT_NEED_UNLOAD: 152 /* this immediate mount needs to */ 153 /* wait for an unload */ 154 cmd->cmd_state = 1; 155 mms_trace(MMS_DEVP, 156 "mount waiting " 157 "for unload to complete"); 158 return (1); 159 160 case MM_MOUNT_NOT_READY: 161 /* Error code should be set */ 162 mms_trace(MMS_ERR, 163 "blocking mount not ready, " 164 "wait longer and try later"); 165 return (0); 166 167 default: 168 mms_trace(MMS_ERR, 169 "bad rc mm_mount_ready"); 170 mm_system_error(cmd, 171 "bad rc mm_mount_ready"); 172 cmd->cmd_remove = 1; 173 mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf); 174 return (0); 175 } 176 177 } 178 179 180 181 PGresult* tm_get_inuse_carts(mm_command_t *cmd, mm_data_t *mm_data) { 182 /* returns ordered list of inuse candidate cartridges */ 183 /* for task_id */ 184 185 mm_db_t *db = &mm_data->mm_db_tm; 186 char *task_id = cmd->cmd_uuid; 187 188 if (mm_db_exec(HERE, db, "select \"CartridgeID\" " 189 "from \"CARTRIDGE\" " 190 "where \"CartridgeStatus\" = 'in use' " 191 "and \"CartridgeID\" " 192 "in (select distinct \"CartridgeID\" " 193 "from \"TASKCARTRIDGE\" " 194 "where \"TaskID\" = '%s') " 195 "order by \"CartridgeNumberMounts\";", 196 task_id) != MM_DB_DATA) { 197 mms_trace(MMS_ERR, 198 "db_error, tm_get_inuse_carts"); 199 return (NULL); 200 } 201 return (db->mm_db_results); 202 } 203 204 int 205 tm_can_dispatch_unmount(mm_command_t *cmd, mm_data_t *mm_data) 206 { 207 mm_db_t *db = &mm_data->mm_db_tm; 208 mm_wka_t *mm_wka = cmd->wka_ptr; 209 210 int rc; 211 212 mms_trace(MMS_DEVP, 213 "tm_can_dispatch_unmount"); 214 215 rc = mm_unmount_ready(mm_wka, cmd, db); 216 switch (rc) { 217 218 case MM_UNMOUNT_ERROR: 219 /* Error code should be set */ 220 mms_trace(MMS_ERR, 221 "internal error, mm_unmount_ready"); 222 cmd->cmd_remove = 1; 223 mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf); 224 return (0); 225 226 case MM_UNMOUNT_READY: 227 /* The unmount is ready, unmount_info should be set */ 228 /* continue to state 1 */ 229 cmd->cmd_state = 1; 230 mms_trace(MMS_DEVP, 231 "unmount is ready to go, " 232 "continue to state 1"); 233 return (1); 234 235 case MM_UNMOUNT_NOT_READY: 236 /* Error code should be set */ 237 mms_trace(MMS_ERR, 238 "blocking unmount not ready, " 239 "wait longer and try later"); 240 return (0); 241 default: 242 mms_trace(MMS_ERR, 243 "bad rc mm_unmount_ready"); 244 mm_system_error(cmd, 245 "bad rc mm_unmount_ready"); 246 cmd->cmd_remove = 1; 247 mm_send_text(mm_wka->mm_wka_conn, cmd->cmd_buf); 248 return (0); 249 } 250 251 } 252 253 int 254 mm_be_remove_non_ready(mm_command_t *cmd) { 255 cmd_mount_info_t *mount_info = &cmd->cmd_mount_info; 256 cmi_cart_list_t *cart = NULL; 257 cmi_drive_list_t *drive = NULL; 258 mms_list_foreach(&mount_info->cmi_cart_list, cart) { 259 if (cart->cmi_cart_not_ready) { 260 cart->cmi_remove_cart = 1; 261 } 262 mms_list_foreach(&cart->cmi_drive_list, drive) { 263 if (drive->cmi_drive_not_ready) { 264 drive->cmi_remove_drive = 1; 265 } 266 } 267 } 268 mm_mount_clean_candidates(cmd); 269 return (0); 270 } 271 272 int 273 tm_be_unmount_ready(mm_wka_t *mm_wka, mm_command_t *cmd, mm_db_t *db, 274 mm_command_t *end_cmd) { 275 cmd_mount_info_t *mount_info = &cmd->cmd_mount_info; 276 277 PGresult *cart_results; 278 int cart_rows; 279 280 int found_cart_drive = 0; 281 int found_ready_cart_drive = 0; 282 283 cmi_cart_list_t *cart = NULL; 284 cmi_drive_list_t *drive = NULL; 285 286 /* Do drive/cart/lib selection using path matching */ 287 if ((cart_results = mm_unmount_cart_results(mm_wka, 288 cmd, db)) == NULL) { 289 mm_system_error(end_cmd, 290 "error getting candidate " 291 "cartridge"); 292 /* No carts or error */ 293 return (MM_UNMOUNT_ERROR); 294 } 295 296 cart_rows = PQntuples(cart_results); 297 mms_trace(MMS_DEVP, "Number of Cartridges is %d", cart_rows); 298 if (cart_rows == 0) { 299 /* No Cartridge Matches Error */ 300 mms_trace(MMS_INFO, 301 "match statment in mount " 302 "didn't match any cartridge/volumes"); 303 mm_response_error(end_cmd, 304 ECLASS_EXPLICIT, ENOMATCH, 305 MM_5052_MSG, 306 NULL); 307 mm_clear_db(&cart_results); 308 return (MM_UNMOUNT_ERROR); 309 } 310 311 /* Create the list objects for */ 312 /* every cartridge/drive candidate */ 313 if (mm_mount_init_candidates(cmd, cart_results, 314 db)) { 315 mms_trace(MMS_ERR, 316 "error initializing candidate lists"); 317 /* err buf should be set by mm_mount_init */ 318 /* so return and remove */ 319 mm_system_error(end_cmd, 320 "error init candidate lists"); 321 return (MM_UNMOUNT_ERROR); 322 } 323 mms_trace(MMS_DEVP, "candidate list created, check availability "); 324 325 /* Check the availability of the candidates */ 326 if (mm_mount_check_candidates(mm_wka, cmd, 327 db)) { 328 mms_trace(MMS_ERR, 329 "error checking candidate lists"); 330 mm_system_error(end_cmd, 331 "error checking candidate lists"); 332 return (MM_UNMOUNT_ERROR); 333 } 334 mms_trace(MMS_DEVP, "done checking list"); 335 336 /* Print mount information */ 337 mm_print_mount_summary(mm_wka, cmd); 338 found_cart_drive = 0; 339 found_ready_cart_drive = 0; 340 341 mms_list_foreach(&mount_info->cmi_cart_list, cart) { 342 mms_list_foreach(&cart->cmi_drive_list, drive) { 343 found_cart_drive = 1; 344 if ((cart->cmi_cart_not_ready == 0) && 345 (drive->cmi_drive_not_ready == 0)) { 346 found_ready_cart_drive = 1; 347 } 348 } 349 } 350 351 352 /* If there is a library or drive error */ 353 /* the error buff has already been set */ 354 if (found_cart_drive == 0) { 355 mms_trace(MMS_ERR, 356 "No candidate " 357 "cartridge/library/drive " 358 "combination found"); 359 mm_response_error(end_cmd, 360 ECLASS_EXPLICIT, 361 "ENOSOLUTIONS", 362 MM_5105_MSG, 363 NULL); 364 return (MM_UNMOUNT_ERROR); 365 } 366 if (found_ready_cart_drive == 0) { 367 mms_trace(MMS_ERR, 368 "candidate " 369 "cartridge/library/drive " 370 "combination found, but is not ready"); 371 mm_response_error(end_cmd, 372 ECLASS_RETRY, 373 "ETMPUNAVAIL", 374 MM_5104_MSG, 375 NULL); 376 return (MM_UNMOUNT_NOT_READY); 377 } 378 379 return (MM_UNMOUNT_READY); 380 381 } 382 383 int 384 tm_be_mount_ready(mm_wka_t *mm_wka, mm_command_t *cmd, mm_db_t *db, 385 mm_command_t *end_cmd) { 386 cmd_mount_info_t *mount_info = &cmd->cmd_mount_info; 387 388 PGresult *cart_results; 389 int cart_rows; 390 391 cmi_cart_list_t *cart = NULL; 392 cmi_drive_list_t *drive = NULL; 393 394 395 int found_cart_drive = 0; 396 int found_ready_cart_drive = 0; 397 398 char *err_text = NULL; 399 400 401 /* Need to set end_cmd buf correctly for any MM_MOUNT_ERROR return */ 402 403 404 /* Do drive/cart/lib selection using path matching */ 405 if ((cart_results = mm_mount_cart_results(mm_wka, 406 cmd, db)) == NULL) { 407 mm_system_error(end_cmd, 408 "error getting candidate " 409 "cartridge"); 410 /* No carts or error */ 411 return (MM_MOUNT_ERROR); 412 } 413 414 cart_rows = PQntuples(cart_results); 415 mms_trace(MMS_DEVP, "Number of Cartridges is %d", cart_rows); 416 417 if (cart_rows == 0) { 418 /* No Cartridge Matches Error */ 419 mms_trace(MMS_INFO, 420 "match statment in mount " 421 "didn't match any cartridge/volumes"); 422 mm_response_error(end_cmd, 423 ECLASS_EXPLICIT, ENOMATCH, 424 MM_5052_MSG, 425 NULL); 426 mm_clear_db(&cart_results); 427 return (MM_MOUNT_ERROR); 428 } 429 /* Create the list objects for */ 430 /* every cartridge/drive candidate */ 431 if (mm_mount_init_candidates(cmd, cart_results, 432 db)) { 433 mms_trace(MMS_ERR, 434 "error initializing candidate lists"); 435 /* err buf should be set by mm_mount_init */ 436 /* so return and remove */ 437 mm_system_error(end_cmd, 438 "error init candidate lists"); 439 mm_clear_db(&cart_results); 440 return (MM_MOUNT_ERROR); 441 } 442 mms_trace(MMS_DEVP, "candidate list created, check availability "); 443 mm_clear_db(&cart_results); 444 445 /* Check the availability of the candidates */ 446 if (mm_mount_check_candidates(mm_wka, cmd, 447 db)) { 448 mms_trace(MMS_ERR, 449 "error checking candidate lists"); 450 mm_system_error(end_cmd, 451 "error checking candidate lists"); 452 return (MM_MOUNT_ERROR); 453 } 454 mms_trace(MMS_DEVP, "done checking list"); 455 456 /* Print mount information */ 457 mm_print_mount_summary(mm_wka, cmd); 458 459 460 /* 461 * For blocking mounts, 462 * check that at least some cart/drive combo exists 463 * if that cart/drive exists, but is not ready, return not ready 464 * 465 * for immediate mounts, check that at least one combination exists 466 */ 467 468 found_cart_drive = 0; 469 found_ready_cart_drive = 0; 470 471 mms_list_foreach(&mount_info->cmi_cart_list, cart) { 472 mms_list_foreach(&cart->cmi_drive_list, drive) { 473 found_cart_drive = 1; 474 if ((cart->cmi_cart_not_ready == 0) && 475 (drive->cmi_drive_not_ready == 0)) { 476 found_ready_cart_drive = 1; 477 } 478 } 479 } 480 481 482 /* If there is a library or drive error */ 483 /* the error buff has already been set */ 484 if (found_cart_drive == 0) { 485 mms_trace(MMS_ERR, 486 "No candidate " 487 "cartridge/library/drive " 488 "combination found"); 489 490 /* If this cmd has a retry error class */ 491 /* Send a retry error */ 492 if (strcmp(cmd->cmd_eclass, ECLASS_RETRY) == 0) { 493 /* This is a retry error */ 494 mms_trace(MMS_ERR, 495 "Error is from a retry error"); 496 497 mm_response_error(end_cmd, 498 ECLASS_RETRY, 499 "ETMPUNAVAIL", 500 MM_5104_MSG, 501 NULL); 502 return (MM_MOUNT_ERROR); 503 } 504 err_text = mm_return_err_text(cmd->cmd_err_ptr); 505 mm_response_error(end_cmd, 506 ECLASS_EXPLICIT, 507 "ENOSOLUTIONS", 508 MM_5110_MSG, 509 "err_text", err_text, 510 NULL); 511 free(err_text); 512 return (MM_MOUNT_ERROR); 513 } 514 if (found_ready_cart_drive == 0) { 515 mms_trace(MMS_ERR, 516 "candidate " 517 "cartridge/library/drive " 518 "combination found, but is not ready"); 519 520 mm_response_error(end_cmd, 521 ECLASS_RETRY, 522 "ETMPUNAVAIL", 523 MM_5104_MSG, 524 NULL); 525 526 return (MM_MOUNT_NOT_READY); 527 } 528 529 return (MM_MOUNT_READY); 530 } 531 532 #define TM_CANCEL_RESPONSE "response task[\"%s\"] cancelled;" 533 534 void 535 mm_cancel_cmd_buf(mm_command_t *cmd) { 536 char *buf = NULL; 537 buf = mms_strnew(TM_CANCEL_RESPONSE, cmd->cmd_task); 538 SQL_CHK_LEN(&cmd->cmd_buf, 0, 539 &cmd->cmd_bufsize, strlen(buf) + 1); 540 strcpy(cmd->cmd_buf, buf); 541 free(buf); 542 buf = NULL; 543 return; 544 no_mem: 545 MM_ABORT_NO_MEM(); 546 } 547 548 void 549 tm_be_cancel_all(mm_command_t *cmd) { 550 mm_command_t *cur_cmd; 551 552 /* Send cancel for all commands in this group */ 553 mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) { 554 mm_cancel_cmd_buf(cur_cmd); 555 556 mm_send_text(cur_cmd->wka_ptr->mm_wka_conn, 557 cur_cmd->cmd_buf); 558 } 559 560 } 561 562 int 563 tm_be_set_mount(mm_command_t *cmd, mm_db_t *db, 564 mm_command_t *end_cmd) { 565 cmd_mount_info_t *mount_info = &cmd->cmd_mount_info; 566 567 char *drive_to_unload = NULL; 568 char *lib_to_unload = NULL; 569 570 571 572 /* cmd is the mount command */ 573 MM_SET_FLAG(cmd->cmd_flags, 574 MM_CMD_DISPATCHABLE); 575 cmd->cmd_state = 1; 576 577 /* This code is the same code as is in mm_set_immediate_mount */ 578 /* make a common function?? */ 579 if (mm_mount_candidate_loaded(cmd)) { 580 mms_trace(MMS_DEVP, 581 "a candidate cartridge is loaded"); 582 mount_info->cmi_mount_type = 583 MM_CANDIDATE_LOADED; 584 } else if (mm_mount_open_drive(cmd)) { 585 mms_trace(MMS_DEVP, 586 "open drive found"); 587 mount_info->cmi_mount_type = 588 MM_OPEN_DRIVE; 589 } else if (mm_mount_loaded_drive(cmd, db, &drive_to_unload, 590 &lib_to_unload)) { 591 /* 2 mount time */ 592 /* these mounts need an unmount, then mount */ 593 if (drive_to_unload == NULL && 594 lib_to_unload == NULL) { 595 mount_info->cmi_mount_type = 596 MM_UNMOUNT_DRIVE; 597 mms_trace(MMS_DEVP, 598 "drive loaded with non-candidate " 599 "must unload 1st"); 600 /* Need to set up parent command */ 601 /* return as dispatch depend */ 602 mms_trace(MMS_DEVP, 603 "%s needs unload to complete first", 604 mount_info->cmi_drive); 605 MM_UNSET_FLAG(cmd->cmd_flags, 606 MM_CMD_DISPATCHABLE); 607 } else { 608 mms_trace(MMS_DEVP, 609 "candidate loaded in non-candidate drive " 610 "must unload 1st"); 611 /* Need to set up parent command */ 612 /* return as dispatch depend */ 613 mms_trace(MMS_DEVP, 614 "%s needs unload to complete first", 615 drive_to_unload); 616 mount_info->cmi_mount_type = 617 MM_UNMOUNT_CART; 618 mount_info->cmi_first_drive = 619 strdup(drive_to_unload); 620 mount_info->cmi_first_lib = 621 strdup(lib_to_unload); 622 MM_UNSET_FLAG(cmd->cmd_flags, 623 MM_CMD_DISPATCHABLE); 624 free(drive_to_unload); 625 free(lib_to_unload); 626 } 627 } else if (mm_unmount_2_drive(cmd, db)) { 628 /* 3 mount time */ 629 /* Candidate cart is mounted, */ 630 /* the only candidate drive is loaded with non-candidate */ 631 /* need to unmount candidate cart, unmount candidate drive */ 632 /* then mount candidate cart/drive */ 633 MM_UNSET_FLAG(cmd->cmd_flags, MM_CMD_DISPATCHABLE); 634 635 } else { 636 mms_trace(MMS_ERR, 637 "no drives found due to other candidates"); 638 mm_set_least_severe(cmd); 639 if (cmd->cmd_err_ptr == NULL) { 640 mms_trace(MMS_ERR, 641 "cmd has no errors, set ENOMATCH"); 642 mm_response_error(end_cmd, 643 ECLASS_EXPLICIT, ENOMATCH, 644 MM_5052_MSG, 645 NULL); 646 } 647 return (MM_BE_ERROR); 648 } 649 650 /* Select Is done - print the results */ 651 mms_trace(MMS_DEVP, "Cart/Lib/Drive selection " 652 "complete for task %s", 653 cmd->cmd_uuid); 654 mms_trace(MMS_DEVP, "Cartridge ID is %s", 655 mount_info->cmi_cartridge); 656 mms_trace(MMS_DEVP, "Library is %s", 657 mount_info->cmi_library); 658 mms_trace(MMS_DEVP, "Drive is %s", 659 mount_info->cmi_drive); 660 mms_trace(MMS_DEVP, "DM is %s", 661 mount_info->cmi_dm); 662 663 /* since this mount will work, clear the error flags for it */ 664 if (cmd->cmd_eclass != NULL) { 665 free(cmd->cmd_eclass); 666 cmd->cmd_eclass = NULL; 667 } 668 if (cmd->cmd_ecode != NULL) { 669 free(cmd->cmd_ecode); 670 cmd->cmd_ecode = NULL; 671 } 672 cmd->cmd_mount_info.cmi_mount_ok = 1; 673 674 return (MM_BE_DISPATCH); 675 } 676 677 int 678 tm_be_set_unmount(mm_wka_t *mm_wka, mm_command_t *cmd, 679 mm_command_t *end_cmd) { 680 cmd_mount_info_t *mount_info = &cmd->cmd_mount_info; 681 682 cmi_cart_list_t *cart = NULL; 683 cmi_drive_list_t *drive = NULL; 684 685 char *cur_cartid = NULL; 686 char *cur_library = NULL; 687 char *cur_dm = NULL; 688 char *cur_drive = NULL; 689 690 /* cmd is the unmount command */ 691 692 cart = mms_list_head(&mount_info->cmi_cart_list); 693 if (cart == NULL) { 694 mm_response_error(end_cmd, 695 ECLASS_RETRY, 696 "ETMPUNAVAIL", 697 MM_5104_MSG, 698 NULL); 699 if (mm_wka->wka_begin_end.be_mode == 700 ACCESS_MODE_BLOCKING) { 701 return (MM_BE_BLOCKING); 702 } 703 mms_trace(MMS_ERR, 704 "unmount has no candidates" 705 " due to other unmount"); 706 return (MM_BE_ERROR); 707 } 708 cur_library = cart->cmi_library; 709 cur_cartid = cart->cmi_cart_id; 710 711 drive = mms_list_head(&cart->cmi_drive_list); 712 if (drive == NULL) { 713 mm_response_error(end_cmd, 714 ECLASS_RETRY, 715 "ETMPUNAVAIL", 716 MM_5104_MSG, 717 NULL); 718 if (mm_wka->wka_begin_end.be_mode == 719 ACCESS_MODE_BLOCKING) { 720 return (MM_BE_BLOCKING); 721 } 722 mms_trace(MMS_ERR, 723 "unmount has no candidates" 724 " due to other unmount"); 725 return (MM_BE_ERROR); 726 } 727 728 cur_drive = drive->cmi_drive_name; 729 cur_dm = drive->cmi_dm_name; 730 731 732 mm_set_mount_info_cart(cur_cartid, 733 mount_info); 734 mm_set_mount_info_drive(cur_drive, 735 mount_info); 736 mm_set_mount_info_dm(cur_dm, 737 mount_info); 738 mm_set_mount_info_library(cur_library, 739 mount_info); 740 741 /* Select Is done - print the results */ 742 mms_trace(MMS_DEVP, "Cart/Lib/Drive selection " 743 "complete for task %s", 744 cmd->cmd_uuid); 745 mms_trace(MMS_DEVP, "Cartridge ID is %s", 746 mount_info->cmi_cartridge); 747 mms_trace(MMS_DEVP, "Library is %s", 748 mount_info->cmi_library); 749 mms_trace(MMS_DEVP, "Drive is %s", 750 mount_info->cmi_drive); 751 mms_trace(MMS_DEVP, "DM is %s", 752 mount_info->cmi_dm); 753 754 return (MM_BE_DISPATCH); 755 } 756 757 void 758 tm_be_rm_error_candidates(mm_command_t *cmd, mm_command_t *err_cmd) { 759 /* remove candidates set in err_cmd */ 760 /* from the beginend candidatea list in cmd */ 761 762 mm_cmd_err_t *err = err_cmd->cmd_err_ptr; 763 mm_command_t *cur_cmd; 764 cmd_mount_info_t *cur_mount_info; 765 766 cmi_cart_list_t *cart = NULL; 767 cmi_drive_list_t *drive = NULL; 768 769 mms_list_t *cart_list; 770 771 int seen_same = 0; 772 mm_cmd_err_t *cur_err = NULL; 773 774 mms_trace(MMS_DEVP, 775 "tm_be_rm_error_candidates: "); 776 if (err == NULL) { 777 mms_trace(MMS_ERR, 778 "tm_be_rm_error_candidates: " 779 "error ptr set to NULL"); 780 return; 781 } 782 783 mms_trace(MMS_DEVP, 784 " Error to remove:"); 785 mm_print_err(err); 786 787 mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) { 788 /* same command */ 789 if (cur_cmd == err_cmd) { 790 seen_same = 1; 791 continue; 792 } 793 if (seen_same == 0) { 794 continue; 795 } 796 797 /* check cur_cmd's error */ 798 mms_list_foreach(&cur_cmd->cmd_err_list, cur_err) { 799 if (mm_same_err(err, cur_err)) { 800 cur_err->err_already_used = 1; 801 mms_trace(MMS_DEVP, 802 " matched an err"); 803 } 804 } 805 cur_cmd->cmd_err_ptr = NULL; 806 mm_set_least_severe(cur_cmd); 807 808 cur_mount_info = &cur_cmd->cmd_mount_info; 809 cart_list = &cur_mount_info->cmi_cart_list; 810 mms_list_foreach(cart_list, cart) { 811 /* Check this cart */ 812 if ((err->retry_cart != NULL) && 813 (cart->cmi_cart_id != NULL) && 814 (strcmp(err->retry_cart, 815 cart->cmi_cart_id) == 0)) { 816 cart->cmi_cart_used = 1; 817 mms_trace(MMS_DEVP, 818 "tm_be_rm_error_candidates: " 819 "set a cart as used"); 820 } 821 mms_list_foreach(&cart->cmi_drive_list, drive) { 822 /* check this drive */ 823 if ((err->retry_drive != NULL) && 824 (drive->cmi_drive_name != NULL) && 825 (strcmp(err->retry_drive, 826 drive->cmi_drive_name) == 0)) { 827 drive->cmi_drive_used = 1; 828 mms_trace(MMS_DEVP, 829 "tm_be_rm_error_candidates: " 830 "set a drive as used"); 831 } 832 } 833 } 834 } 835 } 836 837 void 838 tm_be_rm_mount_candidates(mm_command_t *cmd, mm_command_t *set_cmd) { 839 /* remove candidates set in set_cmd */ 840 /* from the beginend candidatea list in cmd */ 841 mm_command_t *cur_cmd; 842 cmd_mount_info_t *set_mount_info = &set_cmd->cmd_mount_info; 843 cmd_mount_info_t *cur_mount_info; 844 845 cmi_cart_list_t *cart = NULL; 846 cmi_drive_list_t *drive = NULL; 847 848 mms_list_t *cart_list; 849 850 int seen_same = 0; 851 852 mms_trace(MMS_DEVP, 853 "set %s and %s as used candidates", 854 set_mount_info->cmi_cartridge, 855 set_mount_info->cmi_drive); 856 mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) { 857 /* same command */ 858 if (cur_cmd == set_cmd) { 859 seen_same = 1; 860 continue; 861 } 862 if (seen_same == 0) { 863 continue; 864 } 865 cur_mount_info = &cur_cmd->cmd_mount_info; 866 cart_list = &cur_mount_info->cmi_cart_list; 867 mms_list_foreach(cart_list, cart) { 868 if (strcmp(set_mount_info->cmi_cartridge, 869 cart->cmi_cart_id) == 0) { 870 cart->cmi_cart_used = 1; 871 } 872 mms_list_foreach(&cart->cmi_drive_list, drive) { 873 if (strcmp(set_mount_info->cmi_drive, 874 drive->cmi_drive_name) == 0) { 875 drive->cmi_drive_used = 1; 876 } 877 } 878 } 879 } 880 } 881 882 void 883 tm_be_rm_unmount_candidates(mm_command_t *cmd, mm_command_t *set_cmd) { 884 /* remove candidates set in set_cmd */ 885 /* from the beginend candidatea list in cmd */ 886 mm_command_t *cur_cmd; 887 cmd_mount_info_t *set_mount_info = &set_cmd->cmd_mount_info; 888 cmd_mount_info_t *cur_mount_info; 889 cmi_cart_list_t *cart = NULL; 890 891 cmi_drive_list_t *drive = NULL; 892 893 894 mms_list_t *cart_list; 895 896 int seen_same = 0; 897 898 mms_trace(MMS_DEVP, 899 "remove %s and %s from candidate lists", 900 set_mount_info->cmi_cartridge, 901 set_mount_info->cmi_drive); 902 mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) { 903 if (cur_cmd->cmd_func == mm_mount_cmd_func) { 904 /* not an unmount */ 905 continue; 906 } 907 /* same command */ 908 if (cur_cmd == set_cmd) { 909 seen_same = 1; 910 continue; 911 } 912 if (seen_same == 0) { 913 continue; 914 } 915 cur_mount_info = &cur_cmd->cmd_mount_info; 916 cart_list = &cur_mount_info->cmi_cart_list; 917 mms_list_foreach(cart_list, cart) { 918 if (strcmp(set_mount_info->cmi_cartridge, 919 cart->cmi_cart_id) == 0) { 920 cart->cmi_remove_cart = 1; 921 } 922 mms_list_foreach(&cart->cmi_drive_list, drive) { 923 if (strcmp(set_mount_info->cmi_drive, 924 drive->cmi_drive_name) == 0) { 925 drive->cmi_remove_drive = 1; 926 } 927 } 928 } 929 mm_mount_clean_candidates(cur_cmd); 930 } 931 } 932 933 int 934 tm_be_is_in_unmount(char *drive_name, mm_command_t *end_cmd) { 935 mm_command_t *cur_cmd; 936 937 mms_list_foreach(&end_cmd->cmd_beginend_list, cur_cmd) { 938 if (cur_cmd->cmd_func == mm_mount_cmd_func) { 939 /* not an unmount */ 940 continue; 941 } 942 if (strcmp(cur_cmd->cmd_mount_info.cmi_drive, 943 drive_name) == 0) { 944 return (1); 945 } 946 } 947 return (0); 948 } 949 950 int 951 tm_be_init_mount(mm_command_t *end_cmd, mm_db_t *db) { 952 /* this function needs to initialize the mount cmd's */ 953 /* Candidate lists using the selected carts/drives */ 954 /* in the unmount commands */ 955 /* tm_be_match_mount will match mounts to unmounts */ 956 957 PGresult *cart_results; 958 int cart_rows; 959 960 mm_wka_t *mm_wka = end_cmd->wka_ptr; 961 962 mm_command_t *cur_cmd; 963 964 cmi_cart_list_t *cart = NULL; 965 cmi_drive_list_t *drive = NULL; 966 mms_list_t *cart_list; 967 968 mms_list_foreach(&end_cmd->cmd_beginend_list, cur_cmd) { 969 /* Do drive/cart/lib selection using path matching */ 970 if ((cart_results = mm_mount_cart_results(mm_wka, 971 cur_cmd, db)) == NULL) { 972 mm_system_error(end_cmd, 973 "error getting candidate " 974 "cartridge"); 975 /* No carts or error */ 976 return (MM_BE_ERROR); 977 } 978 cart_rows = PQntuples(cart_results); 979 mms_trace(MMS_DEVP, "Number of Cartridges is %d", cart_rows); 980 981 if (cart_rows == 0) { 982 /* No Cartridge Matches Error */ 983 mms_trace(MMS_INFO, 984 "match statment in mount " 985 "didn't match any cartridge/volumes"); 986 mm_response_error(end_cmd, 987 ECLASS_EXPLICIT, ENOMATCH, 988 MM_5052_MSG, 989 NULL); 990 mm_clear_db(&cart_results); 991 return (MM_BE_ERROR); 992 } 993 994 /* Create the list objects for */ 995 /* every cartridge/drive candidate */ 996 if (mm_mount_init_candidates(cur_cmd, cart_results, 997 db)) { 998 mms_trace(MMS_ERR, 999 "error initializing candidate lists"); 1000 /* err buf should be set by mm_mount_init */ 1001 /* so return and remove */ 1002 mm_system_error(end_cmd, 1003 "error init candidate lists"); 1004 mm_clear_db(&cart_results); 1005 return (MM_BE_ERROR); 1006 } 1007 mm_clear_db(&cart_results); 1008 } 1009 1010 mms_trace(MMS_DEVP, 1011 "keep only drive candidates selected in unmount cmd"); 1012 /* Keep only the drive candidates selected in a unmount command */ 1013 mms_list_foreach(&end_cmd->cmd_beginend_list, cur_cmd) { 1014 if (cur_cmd->cmd_func == mm_unmount_cmd_func) { 1015 /* not an mount */ 1016 continue; 1017 } 1018 cart_list = &cur_cmd->cmd_mount_info.cmi_cart_list; 1019 mms_list_foreach(cart_list, cart) { 1020 mms_list_foreach(&cart->cmi_drive_list, drive) { 1021 mms_trace(MMS_DEVP, 1022 " check if %s is selected in an unmount", 1023 drive->cmi_drive_name); 1024 if (tm_be_is_in_unmount(drive->cmi_drive_name, 1025 end_cmd) == 0) { 1026 mms_trace(MMS_DEVP, 1027 " remove this drive"); 1028 drive->cmi_remove_drive = 1; 1029 } else { 1030 mms_trace(MMS_DEVP, 1031 " keep this drive"); 1032 drive->cmi_remove_drive = 0; 1033 } 1034 } 1035 } 1036 mm_mount_clean_candidates(cur_cmd); 1037 } 1038 return (MM_BE_OK); 1039 1040 } 1041 int 1042 tm_be_match_mount(mm_command_t *mnt_cmd, mm_command_t *end_cmd, mm_db_t *db) { 1043 /* select the cart drive for this mnt */ 1044 mm_wka_t *mm_wka = end_cmd->wka_ptr; 1045 cmd_mount_info_t *mount_info = &mnt_cmd->cmd_mount_info; 1046 1047 cmi_cart_list_t *cart = NULL; 1048 cmi_drive_list_t *drive = NULL; 1049 1050 char *cur_cartid = NULL; 1051 char *cur_library = NULL; 1052 char *cur_dm = NULL; 1053 char *cur_drive = NULL; 1054 1055 mm_command_t *unmnt_cmd1 = NULL; 1056 mm_command_t *unmnt_cmd2 = NULL; 1057 1058 mm_command_t *cur_cmd; 1059 int found_unmount = 0; 1060 1061 mms_trace(MMS_DEVP, 1062 "tm_be_match_mount"); 1063 MM_UNSET_FLAG(mnt_cmd->cmd_flags, 1064 MM_CMD_DISPATCHABLE); 1065 mnt_cmd->cmd_state = 1; 1066 1067 1068 cart = mms_list_head(&mount_info->cmi_cart_list); 1069 if (cart == NULL) { 1070 mm_response_error(end_cmd, 1071 ECLASS_RETRY, 1072 "ETMPUNAVAIL", 1073 MM_5104_MSG, 1074 NULL); 1075 if (mm_wka->wka_begin_end.be_mode == 1076 ACCESS_MODE_BLOCKING) { 1077 return (MM_BE_BLOCKING); 1078 } 1079 mms_trace(MMS_ERR, 1080 "mount has no candidates"); 1081 return (MM_BE_ERROR); 1082 } 1083 cur_library = cart->cmi_library; 1084 cur_cartid = cart->cmi_cart_id; 1085 1086 drive = mms_list_head(&cart->cmi_drive_list); 1087 if (drive == NULL) { 1088 mm_response_error(end_cmd, 1089 ECLASS_RETRY, 1090 "ETMPUNAVAIL", 1091 MM_5104_MSG, 1092 NULL); 1093 if (mm_wka->wka_begin_end.be_mode == 1094 ACCESS_MODE_BLOCKING) { 1095 return (MM_BE_BLOCKING); 1096 } 1097 mms_trace(MMS_ERR, 1098 "mount has no candidates"); 1099 return (MM_BE_ERROR); 1100 } 1101 1102 cur_drive = drive->cmi_drive_name; 1103 cur_dm = drive->cmi_dm_name; 1104 1105 mm_set_mount_info_cart(cur_cartid, 1106 mount_info); 1107 mm_set_mount_info_drive(cur_drive, 1108 mount_info); 1109 mm_set_mount_info_dm(cur_dm, 1110 mount_info); 1111 mm_set_mount_info_library(cur_library, 1112 mount_info); 1113 1114 /* Select Is done - print the results */ 1115 mms_trace(MMS_DEVP, "Cart/Lib/Drive selection " 1116 "complete for task %s", 1117 mnt_cmd->cmd_uuid); 1118 mms_trace(MMS_DEVP, "Cartridge ID is %s", 1119 mount_info->cmi_cartridge); 1120 mms_trace(MMS_DEVP, "Library is %s", 1121 mount_info->cmi_library); 1122 mms_trace(MMS_DEVP, "Drive is %s", 1123 mount_info->cmi_drive); 1124 mms_trace(MMS_DEVP, "DM is %s", 1125 mount_info->cmi_dm); 1126 1127 1128 mm_remove_all_depend(mnt_cmd); 1129 mms_list_foreach(&end_cmd->cmd_beginend_list, cur_cmd) { 1130 if (cur_cmd->cmd_func == mm_mount_cmd_func) { 1131 /* not an unmount */ 1132 continue; 1133 } 1134 if (strcmp(mount_info->cmi_drive, 1135 cur_cmd->cmd_mount_info.cmi_drive) == 0) { 1136 /* same drive */ 1137 mm_add_depend(mnt_cmd, cur_cmd); 1138 found_unmount = 1; 1139 unmnt_cmd1 = cur_cmd; 1140 } 1141 } 1142 if (found_unmount == 0) { 1143 mm_system_error(end_cmd, 1144 "couldn't find unmount for this mount"); 1145 mms_trace(MMS_ERR, 1146 "couldn't find unmount for this mount"); 1147 return (MM_BE_ERROR); 1148 } 1149 1150 1151 /* Is this cart currently loaded */ 1152 if (mm_db_exec(HERE, db, 1153 "select \"LibraryName\",\"DriveName\" " 1154 "from \"DRIVE\" where \"DRIVE\"." 1155 "\"CartridgePCL\" = (select \"CartridgePCL\" " 1156 "from \"CARTRIDGE\" where \"CartridgeID\" = '%s');", 1157 mount_info->cmi_cartridge) != MM_DB_DATA) { 1158 mms_trace(MMS_ERR, 1159 "tm_be_match_mount: " 1160 "db error getting drive info"); 1161 mm_sql_db_err_rsp_new(end_cmd, db); 1162 return (MM_BE_ERROR); 1163 } 1164 1165 if (PQntuples(db->mm_db_results) == 0) { 1166 /* Cur cart is not loaded */ 1167 mms_trace(MMS_DEVP, 1168 "cartid %s not found in a drive", 1169 mount_info->cmi_cartridge); 1170 } else { 1171 mms_trace(MMS_DEVP, 1172 "need to unmount %s, %s " 1173 "before mount ", 1174 PQgetvalue(db->mm_db_results, 0, 0), 1175 PQgetvalue(db->mm_db_results, 0, 1)); 1176 1177 unmnt_cmd2 = mm_return_unload( 1178 PQgetvalue(db->mm_db_results, 0, 0), 1179 PQgetvalue(db->mm_db_results, 0, 1), 1180 mm_wka->mm_data); 1181 if (unmnt_cmd2 == NULL) { 1182 mm_system_error(end_cmd, 1183 "couldn't find unmount for this mount"); 1184 mms_trace(MMS_ERR, 1185 "couldn't find unmount for this mount"); 1186 return (MM_BE_ERROR); 1187 } 1188 MM_SET_FLAG(unmnt_cmd1->cmd_flags, 1189 MM_CMD_DISPATCHABLE); 1190 MM_UNSET_FLAG(mnt_cmd->cmd_flags, MM_CMD_DISPATCHABLE); 1191 MM_UNSET_FLAG(unmnt_cmd2->cmd_flags, MM_CMD_DISPATCHABLE); 1192 mms_trace(MMS_DEVP, 1193 "unmnt_cmd1->cmd_name == %s (%p)", 1194 unmnt_cmd1->cmd_name, 1195 unmnt_cmd1); 1196 mms_trace(MMS_DEVP, 1197 "unmnt_cmd2->cmd_name == %s (%p)", 1198 unmnt_cmd2->cmd_name, unmnt_cmd2); 1199 mms_trace(MMS_DEVP, 1200 "mnt_cmd->cmd_name == %s (%p)", 1201 mnt_cmd->cmd_name, mnt_cmd); 1202 mm_remove_all_depend(mnt_cmd); 1203 mm_add_depend(unmnt_cmd1, unmnt_cmd2); 1204 mm_add_depend(unmnt_cmd2, mnt_cmd); 1205 } 1206 mm_clear_db(&db->mm_db_results); 1207 mms_trace(MMS_DEVP, 1208 "mount finished setting up"); 1209 return (MM_BE_OK); 1210 } 1211 1212 int 1213 tm_be_pairs(mm_command_t *cmd, mm_data_t *mm_data) { 1214 /* This is what the function may return */ 1215 /* MM_BE_ERROR */ 1216 /* MM_BE_BLOCKING */ 1217 /* MM_BE_DISPATCH */ 1218 /* For BLOCKING and MMS_ERROR, end cmd error buf */ 1219 /* Should be set */ 1220 1221 mm_db_t *db = &mm_data->mm_db_tm; 1222 mm_wka_t *mm_wka = cmd->wka_ptr; 1223 mm_command_t *cur_cmd; 1224 int rc; 1225 mms_trace(MMS_DEVP, 1226 "tm_be_pairs"); 1227 1228 mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) { 1229 if (cur_cmd->cmd_func == mm_mount_cmd_func) { 1230 /* not an unmount */ 1231 continue; 1232 } 1233 1234 rc = tm_be_unmount_ready(cur_cmd->wka_ptr, cur_cmd, db, cmd); 1235 switch (rc) { 1236 1237 case MM_UNMOUNT_ERROR: 1238 /* Error code should be set */ 1239 mms_trace(MMS_ERR, 1240 "internal error, mm_unmount_ready"); 1241 return (MM_BE_ERROR); 1242 1243 case MM_UNMOUNT_READY: 1244 mms_trace(MMS_DEVP, 1245 "unmount is ready to go, "); 1246 break; 1247 1248 case MM_UNMOUNT_NOT_READY: 1249 if (mm_wka->wka_begin_end.be_mode == 1250 ACCESS_MODE_IMMEDIATE) { 1251 /* Error code should be set */ 1252 mms_trace(MMS_ERR, 1253 "immediate begin-end group " 1254 "is not ready"); 1255 return (MM_BE_ERROR); 1256 } 1257 /* Error code should be set */ 1258 mms_trace(MMS_ERR, 1259 "blocking unmount not ready, " 1260 "wait longer and try later"); 1261 return (MM_BE_BLOCKING); 1262 default: 1263 mms_trace(MMS_ERR, 1264 "bad rc mm_unmount_ready"); 1265 mm_system_error(cmd, 1266 "bad rc mm_unmount_ready"); 1267 return (MM_BE_ERROR); 1268 } 1269 } 1270 mms_trace(MMS_DEVP, 1271 "unmounts prepared"); 1272 /* Unmounts prepared/partially ready */ 1273 /* now determine exactly which tapes to unmount */ 1274 mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) { 1275 if (cur_cmd->cmd_func == mm_mount_cmd_func) { 1276 /* not an unmount */ 1277 continue; 1278 } 1279 mms_trace(MMS_DEVP, "set up a unmount for dispatch"); 1280 rc = tm_be_set_unmount(cur_cmd->wka_ptr, 1281 cur_cmd, cmd); 1282 if (rc == MM_BE_ERROR) { 1283 mms_trace(MMS_ERR, "error setting up unmount"); 1284 /* error set for end command already */ 1285 return (MM_BE_ERROR); 1286 } else if (rc == MM_BE_BLOCKING) { 1287 mms_trace(MMS_ERR, 1288 "blocking mount not ready, " 1289 "wait longer and try later"); 1290 return (MM_BE_BLOCKING); 1291 } 1292 /* remove cmi_cart and cmi_drive from */ 1293 /* above from the remaining */ 1294 /* unmount candidates */ 1295 tm_be_rm_unmount_candidates(cmd, cur_cmd); 1296 MM_SET_FLAG(cur_cmd->cmd_flags, 1297 MM_CMD_DISPATCHABLE); 1298 cur_cmd->cmd_state = 1; 1299 cur_cmd->cmd_mount_info.cui_physical = 1; 1300 } 1301 mms_trace(MMS_DEVP, 1302 "unmounts cart/drive selected and set"); 1303 /* All unmount cmds have been set up */ 1304 /* set up each mount using the candidates in unmounts */ 1305 if (tm_be_init_mount(cmd, db) == MM_BE_ERROR) { 1306 mms_trace(MMS_ERR, "error init mounts for unmounts"); 1307 /* error set for end command already */ 1308 return (MM_BE_ERROR); 1309 } 1310 mms_trace(MMS_DEVP, 1311 "mounts initialized"); 1312 mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) { 1313 if (cur_cmd->cmd_func == mm_unmount_cmd_func) { 1314 /* not an mount */ 1315 continue; 1316 } 1317 /* tm_be_match_mount will match this */ 1318 /* mount with an unmount */ 1319 MM_UNSET_FLAG(cur_cmd->cmd_flags, 1320 MM_CMD_DISPATCHABLE); 1321 cur_cmd->cmd_state = 1; 1322 rc = tm_be_match_mount(cur_cmd, cmd, db); 1323 if (rc == MM_BE_ERROR) { 1324 mms_trace(MMS_ERR, "error setting up unmount"); 1325 /* error set for end command already */ 1326 return (MM_BE_ERROR); 1327 } 1328 1329 } 1330 1331 /* All mounts have been setup, */ 1332 /* create the TASK objects */ 1333 mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) { 1334 mm_set_mount_objs(cur_cmd, db); 1335 } 1336 /* Put these mounts on the command queue */ 1337 tm_be_add_mounts(cmd); 1338 1339 /* All mounts are set and ready to go */ 1340 return (MM_BE_DISPATCH); 1341 1342 } 1343 1344 1345 void tm_be_add_mounts(mm_command_t *cmd) { 1346 mm_command_t *next; 1347 mm_command_t *cur; 1348 1349 for (cur = mms_list_head(&cmd->cmd_beginend_list); 1350 cur != NULL; 1351 cur = next) { 1352 next = mms_list_next(&cmd->cmd_beginend_list, cur); 1353 1354 mms_list_remove(&cmd->cmd_beginend_list, 1355 cur); 1356 pthread_mutex_lock(&cmd->wka_ptr->mm_data->mm_queue_mutex); 1357 mms_list_insert_tail(&cmd->wka_ptr->mm_data->mm_cmd_queue, cur); 1358 pthread_mutex_unlock(&cmd->wka_ptr->mm_data->mm_queue_mutex); 1359 } 1360 } 1361 1362 void 1363 mm_be_order_mount_cmds(mm_command_t *cmd) 1364 { 1365 mm_command_t *be_cmd; 1366 mm_command_t *next_cmd; 1367 1368 /* Put mount commands with already loaded cartridges on */ 1369 /* front of begin end mount list. */ 1370 1371 for (be_cmd = mms_list_head(&cmd->cmd_beginend_list); 1372 be_cmd != NULL; 1373 be_cmd = next_cmd) { 1374 next_cmd = mms_list_next(&cmd->cmd_beginend_list, be_cmd); 1375 if (mm_mount_candidate_loaded(be_cmd)) { 1376 mms_list_remove(&cmd->cmd_beginend_list, be_cmd); 1377 mms_list_insert_head(&cmd->cmd_beginend_list, be_cmd); 1378 } 1379 } 1380 } 1381 1382 int 1383 tm_be_mounts(mm_command_t *cmd, mm_data_t *mm_data) { 1384 mm_db_t *db = &mm_data->mm_db_tm; 1385 mm_wka_t *mm_wka = cmd->wka_ptr; 1386 mm_command_t *cur_cmd; 1387 int rc; 1388 1389 /* Errors */ 1390 int mount_has_error = 0; 1391 1392 char *err_text = NULL; 1393 1394 /* This is the function can return */ 1395 /* MM_BE_ERROR */ 1396 /* MM_BE_BLOCKING */ 1397 /* MM_BE_DISPATCH */ 1398 /* For BLOCKING and MMS_ERROR, end cmd error buf */ 1399 /* Should be set */ 1400 1401 mms_trace(MMS_DEVP, 1402 "tm_be_mounts"); 1403 1404 1405 /* Instead of returning set mount_has_error or mount_would_block */ 1406 /* After calling for ever mount generate the correct error code */ 1407 mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) { 1408 cur_cmd->cmd_mount_info.cmi_mount_ok = 0; 1409 rc = tm_be_mount_ready(cur_cmd->wka_ptr, cur_cmd, db, cmd); 1410 switch (rc) { 1411 1412 case MM_MOUNT_ERROR: 1413 /* Error code should be set */ 1414 mms_trace(MMS_ERR, 1415 "tm_be_mounts: " 1416 "internal error, tm_be_mount_ready"); 1417 mount_has_error = 1; 1418 break; 1419 1420 case MM_MOUNT_READY: 1421 /* The mount is ready, mount_info should be set */ 1422 /* continue to state 1 */ 1423 mms_trace(MMS_DEVP, 1424 "tm_be_mounts: " 1425 "mount is ready to go "); 1426 cur_cmd->cmd_mount_info.cmi_mount_ok = 1; 1427 break; 1428 1429 case MM_MOUNT_NEED_UNLOAD: 1430 /* this immediate mount needs to */ 1431 /* wait for an unload */ 1432 mms_trace(MMS_DEVP, 1433 "tm_be_mounts: " 1434 "mount needs to wait " 1435 "for unload to complete"); 1436 cur_cmd->cmd_mount_info.cmi_mount_ok = 1; 1437 break; 1438 1439 case MM_MOUNT_NOT_READY: 1440 mount_has_error = 1; 1441 mms_trace(MMS_ERR, 1442 "tm_be_mounts: " 1443 "mount not ready, " 1444 "wait longer and try later"); 1445 break; 1446 default: 1447 mms_trace(MMS_ERR, 1448 "tm_be_mounts: " 1449 "bad rc mm_mount_ready"); 1450 mm_system_error(cmd, 1451 "bad rc mm_mount_ready"); 1452 return (MM_BE_ERROR); 1453 } 1454 } 1455 1456 1457 /* Determine the correct error code to use for the end command */ 1458 /* Each mount in the group with an error will have ecode and eclass */ 1459 if (mount_has_error) { 1460 mms_trace(MMS_ERR, 1461 "at least one mount had " 1462 "an error for this begin-end"); 1463 1464 /* at least one mount had an error */ 1465 /* for each mount set the least sever errror */ 1466 /* if any mount has a error more severe than retry */ 1467 /* return error for the end command */ 1468 /* since this mount will not work for immediate or blocking */ 1469 mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) { 1470 if (cur_cmd->cmd_mount_info.cmi_mount_ok) { 1471 mms_trace(MMS_ERR, 1472 "tm_be_mounts: " 1473 "this mount is ok, no errors"); 1474 } else { 1475 mms_trace(MMS_ERR, 1476 "tm_be_mounts: " 1477 "this mount has errors, set least severe"); 1478 1479 mm_set_least_severe(cur_cmd); 1480 if (strcmp(cur_cmd->cmd_eclass, 1481 ECLASS_RETRY) != 0) { 1482 /* this is not a retry error class */ 1483 /* return error for this end command */ 1484 mms_trace(MMS_ERR, 1485 "at least one mount's " 1486 "least severe error is" 1487 " more severe than retry, " 1488 "this begin-end group " 1489 "will not work"); 1490 /* One or more mount has errors */ 1491 /* that are non retry */ 1492 err_text = 1493 mm_return_err_text(cur_cmd-> 1494 cmd_err_ptr); 1495 mm_response_error(cmd, 1496 ECLASS_EXPLICIT, 1497 "ENOSOLUTIONS", 1498 MM_5110_MSG, 1499 "err_text", err_text, 1500 NULL); 1501 free(err_text); 1502 return (MM_BE_ERROR); 1503 } 1504 } 1505 } 1506 1507 1508 1509 } 1510 1511 1512 mm_be_order_mount_cmds(cmd); 1513 1514 /* All mounts are either ok or retry */ 1515 /* Determine which error to return/block */ 1516 /* for immediate, return retry or nosolutions */ 1517 /* for blocking, block or return nosolutions */ 1518 1519 1520 /* Mount candidate lists have been set up, */ 1521 /* divide the resources and set up the exact */ 1522 /* Drive/cartridge combination */ 1523 1524 mount_has_error = 0; 1525 mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) { 1526 1527 mms_trace(MMS_DEVP, "set up a mount for dispatch"); 1528 1529 /* tm_be_set_mount returns MM_BE_ERROR or MM_BE_DISPATCH */ 1530 1531 if (cur_cmd->cmd_mount_info.cmi_mount_ok) { 1532 rc = tm_be_set_mount(cur_cmd, 1533 db, cmd); 1534 } else { 1535 rc = MM_BE_ERROR; 1536 } 1537 1538 if (rc == MM_BE_ERROR) { 1539 mount_has_error = 1; 1540 /* If the cur err ptr is null or */ 1541 /* pointing to a non-retry error class */ 1542 /* This begin-end group cannot succeede */ 1543 if ((cur_cmd->cmd_err_ptr == NULL) || 1544 (strcmp(cur_cmd->cmd_err_ptr->eclass, 1545 ECLASS_RETRY) != 0)) { 1546 mms_trace(MMS_ERR, 1547 "tm_be_mounts: " 1548 "There are no valid " 1549 "solutions to this mount "); 1550 1551 err_text = 1552 mm_return_err_text(cur_cmd-> 1553 cmd_err_ptr); 1554 mm_response_error(cmd, 1555 ECLASS_EXPLICIT, 1556 "ENOSOLUTIONS", 1557 MM_5110_MSG, 1558 "err_text", err_text, 1559 NULL); 1560 free(err_text); 1561 return (MM_BE_ERROR); 1562 } 1563 tm_be_rm_error_candidates(cmd, cur_cmd); 1564 } else { 1565 tm_be_rm_mount_candidates(cmd, cur_cmd); 1566 } 1567 } 1568 1569 if (mount_has_error) { 1570 /* If this is immediate, return retry error class for the end */ 1571 /* if this is blocking, then block for the whole group */ 1572 /* Set error for retry */ 1573 mm_response_error(cmd, 1574 ECLASS_RETRY, 1575 "ETMPUNAVAIL", 1576 MM_5104_MSG, 1577 NULL); 1578 return (MM_BE_BLOCKING); 1579 } 1580 mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) { 1581 if (mm_dispatch_now(mm_wka, cur_cmd, db)) { 1582 /* error should be set */ 1583 mms_trace(MMS_ERR, 1584 "error setting up mount for dispatch"); 1585 } 1586 } 1587 /* All mounts have been setup, */ 1588 /* create the TASK objects */ 1589 mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) { 1590 mm_set_mount_objs(cur_cmd, db); 1591 } 1592 /* Put these mounts on the command queue */ 1593 tm_be_add_mounts(cmd); 1594 1595 /* All mounts are set and ready to go */ 1596 return (MM_BE_DISPATCH); 1597 } 1598 1599 int 1600 tm_be_cmd_has_unmounts(mm_command_t *cmd) { 1601 mm_command_t *cur_cmd; 1602 int unmount_count = 0; 1603 int mount_count = 0; 1604 1605 int print_message = 1; 1606 /* Returns 1 if this has unmounts */ 1607 /* Also makes sure unmounts are paird with mounts */ 1608 if (print_message) 1609 mms_trace(MMS_DEVP, 1610 "tm_be_cmd_has_unmounts"); 1611 mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) { 1612 if (cur_cmd->cmd_func == mm_mount_cmd_func) { 1613 if (print_message) 1614 mms_trace(MMS_DEVP, 1615 "saw a mount"); 1616 mount_count ++; 1617 } else if (cur_cmd->cmd_func == mm_unmount_cmd_func) { 1618 if (print_message) 1619 mms_trace(MMS_DEVP, 1620 "saw an unmount"); 1621 unmount_count ++; 1622 } 1623 } 1624 if (unmount_count == 0) 1625 return (0); 1626 if (unmount_count == mount_count) 1627 return (1); 1628 mm_system_error(cmd, 1629 "num mounts does not match num unmounts"); 1630 return (-1); 1631 } 1632 1633 int 1634 tm_can_dispatch_end(mm_command_t *cmd, mm_data_t *mm_data) 1635 { 1636 mm_db_t *db = &mm_data->mm_db_tm; 1637 mm_wka_t *mm_wka = cmd->wka_ptr; 1638 1639 int rc; 1640 int immediate = 0; 1641 int unmount = 0; 1642 1643 if (mm_wka->wka_begin_end.be_mode == 1644 ACCESS_MODE_IMMEDIATE) 1645 immediate = 1; 1646 1647 /* Determine the begin-end type */ 1648 /* Currently there are 2 types */ 1649 /* 1. A group of all mounts */ 1650 /* 2. A group of unmounts paired 1to1 w/mounts */ 1651 if ((unmount = tm_be_cmd_has_unmounts(cmd)) == -1) { 1652 /* Error buf is set */ 1653 goto cmd_error; 1654 } 1655 if (unmount == 1) { 1656 rc = tm_be_pairs(cmd, mm_data); 1657 } else { 1658 rc = tm_be_mounts(cmd, mm_data); 1659 } 1660 switch (rc) { 1661 case MM_BE_BLOCKING: 1662 if (immediate) 1663 goto cmd_error; 1664 return (0); 1665 case MM_BE_DISPATCH: 1666 /* Send success for end */ 1667 mm_path_match_report(cmd, db); 1668 (void) mm_del_tm_cmd(db, cmd->cmd_uuid); 1669 mm_send_response(mm_wka->mm_wka_conn, cmd); 1670 return (1); 1671 case MM_BE_ERROR: 1672 /* Error buf is set */ 1673 goto cmd_error; 1674 } 1675 1676 1677 cmd_error: 1678 /* Error buf must be set */ 1679 (void) mm_del_tm_cmd(db, cmd->cmd_uuid); 1680 cmd->cmd_remove = 1; 1681 mm_send_text(cmd->wka_ptr->mm_wka_conn, 1682 cmd->cmd_buf); 1683 tm_be_cancel_all(cmd); 1684 return (0); 1685 } 1686 1687 int 1688 tm_can_dispatch(char *task_id, mm_data_t *mm_data) 1689 { 1690 1691 mms_list_t *cmd_queue = &mm_data->mm_cmd_queue; 1692 1693 mm_command_t *cur_cmd; 1694 1695 1696 mms_trace(MMS_DEVP, "tm_can_dispatch"); 1697 1698 /* Find the command associated with this task */ 1699 pthread_mutex_lock(&mm_data->mm_queue_mutex); 1700 mms_list_foreach(cmd_queue, cur_cmd) { 1701 if ((strcmp(task_id, 1702 cur_cmd->cmd_uuid) == 0)) { 1703 /* task id matches */ 1704 break; 1705 } 1706 1707 } 1708 pthread_mutex_unlock(&mm_data->mm_queue_mutex); 1709 if (cur_cmd == NULL) { 1710 mms_trace(MMS_INFO, "Could not match task %s with a command", 1711 task_id); 1712 return (0); 1713 } 1714 1715 mms_trace(MMS_DEVP, "Matched Task with command - cmd is %s", 1716 cur_cmd->cmd_uuid); 1717 if (cur_cmd->cmd_remove) { 1718 /* This command has already been marked for removal */ 1719 /* skip and let main thread clean it up */ 1720 mms_trace(MMS_DEVP, 1721 "skip %s, marked for remove", 1722 cur_cmd->cmd_uuid); 1723 return (0); 1724 } 1725 1726 if (cur_cmd->cmd_func == mm_mount_cmd_func) { 1727 pthread_mutex_lock(&cur_cmd->wka_ptr-> 1728 wka_local_lock); 1729 /* Set cmd_dispatchable inside this func */ 1730 if (tm_can_dispatch_mount(cur_cmd, mm_data)) { 1731 pthread_mutex_unlock(&cur_cmd->wka_ptr-> 1732 wka_local_lock); 1733 return (1); 1734 } 1735 pthread_mutex_unlock(&cur_cmd->wka_ptr-> 1736 wka_local_lock); 1737 return (0); 1738 } else if (cur_cmd->cmd_func == mm_unmount_cmd_func) { 1739 pthread_mutex_lock(&cur_cmd->wka_ptr-> 1740 wka_local_lock); 1741 if (tm_can_dispatch_unmount(cur_cmd, mm_data)) { 1742 /* set command as dispatchable */ 1743 MM_SET_FLAG(cur_cmd->cmd_flags, MM_CMD_DISPATCHABLE); 1744 pthread_mutex_unlock(&cur_cmd->wka_ptr-> 1745 wka_local_lock); 1746 return (1); 1747 } 1748 pthread_mutex_unlock(&cur_cmd->wka_ptr-> 1749 wka_local_lock); 1750 1751 return (0); 1752 } else if (cur_cmd->cmd_func == mm_end_cmd_func) { 1753 pthread_mutex_lock(&cur_cmd->wka_ptr-> 1754 wka_local_lock); 1755 if (tm_can_dispatch_end(cur_cmd, mm_data)) { 1756 /* set command as dispatchable */ 1757 MM_SET_FLAG(cur_cmd->cmd_flags, MM_CMD_DISPATCHABLE); 1758 pthread_mutex_unlock(&cur_cmd->wka_ptr-> 1759 wka_local_lock); 1760 return (1); 1761 } 1762 pthread_mutex_unlock(&cur_cmd->wka_ptr-> 1763 wka_local_lock); 1764 } else { 1765 mms_trace(MMS_ERR, 1766 "command is not a mount/unmount or end"); 1767 return (0); 1768 } 1769 return (0); 1770 } 1771 1772 1773 int 1774 mm_get_tm_cmd(mm_data_t *mm_data) 1775 { 1776 mm_db_t *db = &mm_data->mm_db_tm; 1777 PGresult *tasks; 1778 int num_tasks; 1779 int num_dispatched = 0; 1780 int i; 1781 1782 /* used when a mount needs a drive unloaded 1st */ 1783 1784 1785 mms_trace(MMS_DEVP, "mm_get_tm_cmd"); 1786 1787 mms_trace(MMS_DEVP, "Getting list of tasks..."); 1788 1789 /* Get ordered list of blocked tasks */ 1790 if (mm_db_exec(HERE, db, 1791 "select * from " 1792 "(select \"TaskID\"," 1793 "\"TaskPriority\" from \"TASK\" " 1794 "where \"TaskState\" = 'blocked' " 1795 "order by \"TaskArrivalTime\") " 1796 "as foo order by \"TaskPriority\" " 1797 "desc;") != MM_DB_DATA) { 1798 mms_trace(MMS_ERR, 1799 "mm_get_tm_cmd: " 1800 "db error getting task info"); 1801 return (1); 1802 } 1803 1804 tasks = db->mm_db_results; 1805 num_tasks = PQntuples(tasks); 1806 if (num_tasks == 0) { 1807 mms_trace(MMS_DEVP, "%d tasks found", 1808 num_tasks); 1809 mm_clear_db(&tasks); 1810 mms_trace(MMS_DEVP, "TaskManager is Done"); 1811 return (0); 1812 } 1813 mms_trace(MMS_DEVP, "%d tasks found, trying dispatch", 1814 num_tasks); 1815 for (i = 0; i < num_tasks; i++) { 1816 /* Try to dispatch each task */ 1817 mms_trace(MMS_DEVP, " task %s, priority %s", 1818 PQgetvalue(tasks, i, 0), 1819 PQgetvalue(tasks, i, 1)); 1820 1821 if (tm_can_dispatch(PQgetvalue(tasks, i, 0), 1822 mm_data) == 1) { 1823 /* Task ok for dispatch */ 1824 mms_trace(MMS_INFO, "task %s ready for dispatch", 1825 PQgetvalue(tasks, i, 0)); 1826 num_dispatched ++; 1827 } else { 1828 /* Resources not available */ 1829 mms_trace(MMS_DEVP, "task %s not ready", 1830 PQgetvalue(tasks, i, 0)); 1831 } 1832 } 1833 1834 mms_trace(MMS_DEVP, "%d tasks dispatched", 1835 num_dispatched); 1836 1837 if (num_dispatched == 0) { 1838 mms_trace(MMS_DEVP, "TaskManager is Done"); 1839 mm_clear_db(&tasks); 1840 return (0); 1841 } 1842 /* wakeup worker thread to do work */ 1843 1844 pthread_mutex_lock(&mm_data->mm_worker_mutex); 1845 mm_data->mm_work_todo = 1; 1846 pthread_cond_signal(&mm_data->mm_work_cv); 1847 pthread_mutex_unlock(&mm_data->mm_worker_mutex); 1848 1849 1850 mms_trace(MMS_DEVP, "TaskManager is Done"); 1851 mm_clear_db(&tasks); 1852 return (0); 1853 1854 } 1855 1856 mm_db_rval_t 1857 mm_set_tm_task(mm_db_t *db, mm_command_t *command) 1858 { 1859 return (mm_new_tm_task(db, command, "blocked")); 1860 } 1861 1862 mm_db_rval_t 1863 mm_new_tm_task(mm_db_t *db, mm_command_t *command, char *state) 1864 { 1865 mm_db_rval_t rc; 1866 char *cmd_text; 1867 1868 if ((cmd_text = mms_pn_build_cmd_text(command->cmd_root)) == NULL) { 1869 return (MM_DB_ERROR); /* out of memory */ 1870 } 1871 rc = mm_db_exec(HERE, db, "INSERT INTO \"TASK\" " 1872 "(\"TaskID\", \"TaskType\", \"ApplicationName\", " 1873 "\"AIName\", \"TaskStatement\", \"ClientTaskID\", " 1874 "\"TaskState\") VALUES " 1875 "('%s', '%s', '%s', '%s', $$%s$$, '%s', '%s')", 1876 command->cmd_uuid, 1877 command->cmd_root->pn_string, 1878 command->wka_ptr->wka_conn.cci_client, 1879 command->wka_ptr->wka_conn.cci_instance, 1880 cmd_text, command->cmd_task, state); 1881 free(cmd_text); 1882 return (rc); 1883 } 1884 1885 mm_db_rval_t 1886 mm_set_tm_cartridge(mm_db_t *db, char *taskid, char *cartridge_id) 1887 { 1888 mm_db_rval_t rc; 1889 PGresult *task_results; 1890 1891 rc = mm_db_exec(HERE, db, 1892 "select * from \"TASKCARTRIDGE\" where " 1893 "\"TaskID\" = '%s' and \"CartridgeID\" = '%s'", 1894 taskid, cartridge_id); 1895 if (rc != MM_DB_DATA) { 1896 mms_trace(MMS_ERR, 1897 "mm_set_tm_cartridge: " 1898 "db error getting info for" 1899 " TASKCARTRIDGE"); 1900 mm_clear_db(&db->mm_db_results); 1901 return (rc); 1902 } 1903 task_results = db->mm_db_results; 1904 if (PQntuples(task_results) == 0) { 1905 rc = mm_db_exec(HERE, db, "INSERT INTO \"TASKCARTRIDGE\" " 1906 "(\"TaskID\", \"CartridgeID\") VALUES ('%s', '%s')", 1907 taskid, cartridge_id); 1908 if (rc != MM_DB_OK) { 1909 mms_trace(MMS_ERR, 1910 "mm_set_tm_cartridge: " 1911 "db error inserting TASKCARTRIDGE"); 1912 mm_clear_db(&db->mm_db_results); 1913 } 1914 } else { 1915 if (rc == MM_DB_DATA) { 1916 rc = MM_DB_OK; 1917 } 1918 } 1919 mm_clear_db(&task_results); 1920 return (rc); 1921 } 1922 1923 mm_db_rval_t 1924 mm_set_tm_drive(mm_db_t *db, char *taskid, char *drive) 1925 { 1926 mm_db_rval_t rc; 1927 PGresult *task_results; 1928 1929 rc = mm_db_exec(HERE, db, 1930 "select * from \"TASKDRIVE\" where " 1931 "\"TaskID\" = '%s' and \"DriveName\" = '%s'", 1932 taskid, drive); 1933 if (rc != MM_DB_DATA) { 1934 mms_trace(MMS_ERR, 1935 "mm_set_tm_drive: " 1936 "db error getting info for" 1937 " TASKDRIVE"); 1938 mm_clear_db(&db->mm_db_results); 1939 return (rc); 1940 } 1941 task_results = db->mm_db_results; 1942 if (PQntuples(task_results) == 0) { 1943 rc = mm_db_exec(HERE, db, "INSERT INTO \"TASKDRIVE\" " 1944 "(\"TaskID\", \"DriveName\") VALUES ('%s', '%s')", 1945 taskid, drive); 1946 if (rc != MM_DB_OK) { 1947 mms_trace(MMS_ERR, 1948 "mm_set_tm_drive: " 1949 "db error inserting TASKDRIVE"); 1950 mm_clear_db(&db->mm_db_results); 1951 } 1952 } else { 1953 if (rc == MM_DB_DATA) { 1954 rc = MM_DB_OK; 1955 } 1956 } 1957 mm_clear_db(&task_results); 1958 return (rc); 1959 } 1960 1961 mm_db_rval_t 1962 mm_set_tm_library(mm_db_t *db, char *taskid, char *library) 1963 { 1964 mm_db_rval_t rc; 1965 PGresult *task_results; 1966 1967 rc = mm_db_exec(HERE, db, 1968 "select * from \"TASKLIBRARY\" where " 1969 "\"TaskID\" = '%s' and \"LibraryName\" = '%s'", 1970 taskid, library); 1971 if (rc != MM_DB_DATA) { 1972 mms_trace(MMS_ERR, 1973 "mm_set_tm_library: " 1974 "db error getting info for" 1975 " TASKLIBRARY"); 1976 mm_clear_db(&db->mm_db_results); 1977 return (rc); 1978 } 1979 task_results = db->mm_db_results; 1980 if (PQntuples(task_results) == 0) { 1981 rc = mm_db_exec(HERE, db, "INSERT INTO \"TASKLIBRARY\" " 1982 "(\"TaskID\", \"LibraryName\") VALUES ('%s', '%s')", 1983 taskid, library); 1984 if (rc != MM_DB_OK) { 1985 mms_trace(MMS_ERR, 1986 "mm_set_tm_library: " 1987 "db error inserting TASKLIBRARY"); 1988 mm_clear_db(&db->mm_db_results); 1989 } 1990 } else { 1991 if (rc == MM_DB_DATA) { 1992 rc = MM_DB_OK; 1993 } 1994 } 1995 mm_clear_db(&task_results); 1996 return (rc); 1997 } 1998 1999 mm_db_rval_t 2000 mm_set_tm_cmd_dispatched(mm_db_t *db, char *taskid) 2001 { 2002 mm_db_rval_t rc; 2003 2004 rc = mm_db_exec(HERE, db, "UPDATE \"TASK\" " 2005 "SET \"TaskState\" = 'dispatched' " 2006 "WHERE \"TaskID\" = '%s'", taskid); 2007 2008 return (rc); 2009 } 2010 2011 mm_db_rval_t 2012 mm_del_tm_cmd(mm_db_t *db, char *taskid) 2013 { 2014 mm_db_rval_t rc; 2015 2016 rc = mm_db_exec(HERE, db, "DELETE FROM \"TASK\" " 2017 "WHERE \"TaskID\" = '%s'", taskid); 2018 if (rc != MM_DB_OK) { 2019 mms_trace(MMS_ERR, 2020 "mm_del_tm_cmd: " 2021 "db error deleteing from TASK"); 2022 } 2023 2024 rc = mm_db_exec(HERE, db, "delete from \"REQUEST\" where " 2025 "\"RequestingTaskID\" = '%s' and " 2026 "\"RequestState\" != 'responded';", taskid); 2027 2028 if (rc != MM_DB_OK) { 2029 mms_trace(MMS_ERR, 2030 "mm_del_tm_cmd: " 2031 "db error deleteing from REQUEST"); 2032 } 2033 2034 return (rc); 2035 } 2036 2037 mm_db_rval_t 2038 mm_chg_tm_cmd_priority(mm_db_t *db, char *taskid, int priority) 2039 { 2040 mm_db_rval_t rc; 2041 2042 rc = mm_db_exec(HERE, db, "UPDATE \"TASK\" " 2043 "SET \"TaskPriority\" = '%s' " 2044 "WHERE \"TaskID\" = '%s'", priority, taskid); 2045 2046 return (rc); 2047 } 2048