/********************************************************************** create_element (ElementStruct element, int issueHour, char *eleStr, char *errorStr) This function takes information contained in the element structure and creates the string indicating the element type and calls create_area for each area of this type. Input Parameters: element ElementStruct hour int issuance hour of gamet Output Parameters: elementString char string of type and information on each area errorStr char concatenated string of errors occurred while creating area string Functions Called: element_string create_area add_area_errors **********************************************************************/ void create_element (ElementStruct element, int hour, char *elementString, char *errors) { char aString[256]; char estr[64]; int j; int retCode; /* Initial check */ if (element.type >= MAX_ELEMENTS) { if (strlen(errors) == (size_t)0) { sprintf(estr, "Unexpected Element Type."); strcpy (errors, estr); } else { sprintf (estr, "; Unexpected Element Type."); strcat(errors, estr); } /* encountered error, set type to no type */ element.type = no_element_type; } sprintf (elementString, "\n%s: ", element_string (element.type)); /* For each area in an element, create the string */ for (j = 0; j < element.numAreas; j++) { aString[0] = '\0'; retCode = AREA_NO_ERROR; create_area(element.area[j], hour, j, element.type, &retCode, aString); /* check for errors */ if (retCode != AREA_NO_ERROR) add_area_errors (retCode, element.type, j, errors); /* put a period between areas */ if (j < element.numAreas - 1) strcat(aString, ". "); strcat (elementString, aString); } }
/* * move - move from one element to another * * entry - * library - library_t * * event - robo_event_t * */ int move( library_t *library, robo_event_t *event) { dev_ent_t *un; int err = -1, retry, timeout; char *l_mess = library->un->dis_mes[DIS_MES_NORM]; char *MES_9079 = catgets(catfd, SET, 9079, "move from %s to %s %s"); char *mess, *src_mess, *des_mess, *i_mess; robot_internal_t *cmd = &event->request.internal; int added_more_time = FALSE; sam_extended_sense_t *sense = (sam_extended_sense_t *) SHM_REF_ADDR(library->un->sense); int movmed_err; un = library->un; src_mess = element_string(element_type(library, cmd->source)); des_mess = element_string(element_type(library, cmd->destination1)); if (cmd->flags.b.invert1) i_mess = catgets(catfd, SET, 9084, "invert"); else i_mess = ""; mess = (char *)malloc_wait(strlen(MES_9079) + strlen(src_mess) + strlen(des_mess) + strlen(i_mess) + 10, 4, 0); sprintf(mess, MES_9079, src_mess, des_mess, i_mess); memccpy(l_mess, mess, '\0', DIS_MES_LEN); free(mess); DevLog(DL_DETAIL(5057), cmd->source, cmd->flags.b.invert1 ? "invert" : "asis", cmd->destination1); /* * A programming note from DocStore states that you should * allow up to 4 minutes for a move. This is to allow * for recovery and retry by the robot. If other robots need * different time outs, this is the place to put um. */ switch (library->un->type) { case DT_DLT2700: timeout = 300; break; case DT_DOCSTOR: timeout = 4 * 60; break; case DT_METD28: /* FALLTHROUGH */ case DT_METD360: /* FALLTHROUGH */ case DT_SPECLOG: /* FALLTHROUGH */ case DT_ATL1500: /* FALLTHROUGH */ case DT_ODI_NEO: /* FALLTHROUGH */ case DT_QUANTUMC4: /* FALLTHROUGH */ case DT_STK97XX: /* FALLTHROUGH */ case DT_FJNMXX: /* FALLTHROUGH */ case DT_SL3000: /* FALLTHROUGH */ case DT_SLPYTHON: timeout = 10 * 60; break; default: timeout = 5 * 60; break; } mutex_lock(&library->un->io_mutex); retry = 2; do { time_t start; TAPEALERT(library->open_fd, library->un); memset(sense, 0, sizeof (sam_extended_sense_t)); start = time(NULL); movmed_err = scsi_cmd(library->open_fd, library->un, SCMD_MOVE_MEDIUM, timeout, cmd->transport, cmd->source, cmd->destination1, (cmd->flags.b.invert1 ? 1 : 0)); TAPEALERT(library->open_fd, library->un); if (movmed_err < 0) { DevLog(DL_TIME(5177), cmd->source, cmd->flags.b.invert1 ? "invert" : "asis", cmd->destination1, time(NULL) - start); GENERIC_SCSI_ERROR_PROCESSING(library->un, library->scsi_err_tab, 0, err, added_more_time, retry, /* code for DOWN_EQU */ if (!cmd->flags.b.noerror) { err = DOWN_EQU; if (sense->es_add_code == 0x40 && sense->es_qual_code == 0x02) { move_drive_error(library, cmd->source, cmd->destination1, &err); } else { down_library(library, SAM_STATE_CHANGE); } retry = 1; /* MACRO for cstyle */ } break; /* MACRO for cstyle */,
/********************************************************************* add_area_errors (int errorCode, ElementType type, int areaNum, char *errorStr) Based on bits set in errorCode, the function adds information to the errorStr string. See "create_area" above for possible values of errorCode. Information includes the element type and area number containing the error. Check the error, and copy or cat on to the error string. Input Parameters: errorCode int type ElementType areaNum int Output Parameters: errorStr char Functions Called: element_string **********************************************************************/ void add_area_errors (int error_code, ElementType type, int areaNum, char *errors) { int no_errors; /* empty or adding to error string */ char tmp[256]; char *eT; if (strlen (errors)) no_errors = FALSE; else no_errors = TRUE; eT = element_string (type); if (error_code & AREA_BAD_VALID_PERIOD) { if (no_errors) { sprintf(tmp, "%s, Area %d: Bad Valid Period", eT, areaNum+1); strcpy (errors, tmp); } else { sprintf(tmp, "; %s, Area %d: Bad Valid Period", eT, areaNum+1); strcat (errors, tmp); } no_errors = FALSE; } if (error_code & AREA_INVALID_ATTRIBUTE) { if (no_errors) { sprintf(tmp, "%s, Area %d: No Area Attribute", eT, areaNum+1); strcpy (errors, tmp); } else { sprintf(tmp, "; %s, Area %d: No Area Attribute", eT, areaNum+1); strcat (errors, tmp); } no_errors = FALSE; } if (error_code & AREA_INVALID_VORSTRING) { if (no_errors) { sprintf(tmp, "%s, Area %d: No Area Location Information", eT, areaNum+1); strcpy (errors, tmp); } else { sprintf(tmp, "; %s, Area %d: No Area Location Information", eT, areaNum+1); strcat (errors, tmp); } no_errors = FALSE; } if (error_code & AREA_NO_STATE) { if (no_errors) { sprintf(tmp, "%s, Area %d: No Area State Information", eT, areaNum+1); strcpy (errors, tmp); } else { sprintf(tmp, "; %s, Area %d: No Area State Information", eT, areaNum+1); strcat (errors, tmp); } no_errors = FALSE; } if (error_code & AREA_NO_MOVEMENT) { if (no_errors) { sprintf(tmp, "%s, Area %d: No Area Pressure System Movement Information", eT, areaNum+1); strcpy (errors, tmp); } else { sprintf(tmp, "; %s, Area %d: No Area Pressure System Movement Information", eT, areaNum+1); strcat (errors, tmp); } no_errors = FALSE; } }