/* * GetSenseInformation * * Attempt to get SCSI sense information either from the Auto sense * mechanism or by querying manually. */ void IOSCSITape::GetSense(SCSITaskIdentifier request) { SCSI_Sense_Data senseBuffer = { 0 }; bool validSense = false; SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE; IOMemoryDescriptor *bufferDesc = IOMemoryDescriptor::withAddress((void *)&senseBuffer, sizeof(senseBuffer), kIODirectionIn); if (GetTaskStatus(request) == kSCSITaskStatus_CHECK_CONDITION) { validSense = GetAutoSenseData(request, &senseBuffer); if (validSense == false) { if (REQUEST_SENSE(request, bufferDesc, kSenseDefaultSize, 0) == true) serviceResponse = SendCommand(request, kTenSecondTimeoutInMS); if (serviceResponse == kSCSIServiceResponse_TASK_COMPLETE) validSense = true; } if (validSense == true) InterpretSense(&senseBuffer); else STATUS_LOG("invalid or unretrievable SCSI SENSE"); } bufferDesc->release(); }
/* * DoSCSICommand() * Encapsulate super::SendCommand() to handle unexpected service and * task errors as well as hand off to SCSI SENSE interpreter. */ SCSITaskStatus IOSCSITape::DoSCSICommand( SCSITaskIdentifier request, UInt32 timeoutDuration) { SCSITaskStatus taskStatus = kSCSITaskStatus_DeliveryFailure; SCSIServiceResponse serviceResponse = kSCSIServiceResponse_SERVICE_DELIVERY_OR_TARGET_FAILURE; require((request != 0), ErrorExit); serviceResponse = SendCommand(request, timeoutDuration); sense_flags = 0; if (serviceResponse != kSCSIServiceResponse_TASK_COMPLETE) { STATUS_LOG("unknown service response: 0x%x", serviceResponse); goto ErrorExit; } else { taskStatus = GetTaskStatus(request); if (taskStatus == kSCSITaskStatus_CHECK_CONDITION) { /* Get and interpret SCSI SENSE information */ GetSense(request); } else if (taskStatus != kSCSITaskStatus_GOOD) { STATUS_LOG("unknown task status: 0x%x", taskStatus); } else if (taskStatus == kSCSITaskStatus_GOOD) { /* setup flags for device file closing */ if (flags & ST_WRITTEN_TOGGLE) flags |= ST_WRITTEN; else flags &= ~ST_WRITTEN; } } /* clear the write toggle bit in case the next command is not a * write */ flags &= ~ST_WRITTEN_TOGGLE; ErrorExit: return taskStatus; }
int GroupClient::ProcessList( const std::string &infohash, const bool is_full, const bool is_show_history, const bool is_daemon) { std::vector<TaskStatus> task_status_list; PrintListTitle(); if (!is_daemon) { // use no daemon, so just print one line and return if (GetTaskStatus(infohash, is_full, task_status_list) != 0) { fprintf(stderr, "get task status error, infohash[%s], is_full[%d]\n", infohash.c_str(), is_full); return -1; } std::vector<TaskStatus>::iterator it = task_status_list.begin(); for (; it != task_status_list.end(); ++it) { PrintOneTaskStatus(*it, is_show_history); } return 0; } int line_count = 0; while(true) { if (GetTaskStatus(infohash, is_full, task_status_list) != 0) { fprintf(stderr, "get task status error, infohash[%s], is_full[%d]\n", infohash.c_str(), is_full); break; } // clear history print if (line_count != 0) { ClearList(line_count); } bool has_not_finished = false; std::string print_string; line_count = 0; std::vector<TaskStatus>::iterator it = task_status_list.begin(); for (; it != task_status_list.end(); ++it) { std::string task_status_string; if (!it->is_task_finished || it->state == -1) { has_not_finished = true; } task_status_string = GetTaskStatusString(*it, is_show_history); if (task_status_string.empty()) { continue; } print_string.append(task_status_string); // each task status string need 2 line line_count += 2; } // for print_string.append(GetAllTaskSumInfo(task_status_list)); line_count += 2; if (!has_not_finished) { fprintf(stdout, "%s\33[%dA", print_string.c_str(), line_count); break; } fprintf(stdout, "%s\33[%dA", print_string.c_str(), line_count); sleep(1); } // while fprintf(stdout, "\33[%dB\n\33[10000D\33[KAll task finished\n\33[K\33[0m", line_count+1); return 0; }