int ndmca_monitor_backup_tape_tcp (struct ndm_session *sess) { struct ndm_control_agent *ca = sess->control_acb; int count; ndmp9_data_state ds; char *estb; ndmalogf (sess, 0, 3, "Monitoring backup"); for (count = 0; count < 10; count++) { ndmca_mon_wait_for_something (sess, count <= 1 ? 30 : 10); if (ndmca_monitor_get_states(sess) < 0) break; #if 0 if (count > 2) ndmca_mon_show_states(sess); #endif ds = ca->data_state.state; estb = ndmca_data_est(ca); ndmalogf (sess, 0, 1, "DATA: bytes %lldKB%s", ca->data_state.bytes_processed/1024LL, estb ? estb : ""); ca->job.bytes_written = ca->data_state.bytes_processed; if (ds == NDMP9_DATA_STATE_ACTIVE) { count = 0; continue; } /* * If DATA has halted, the show is over. */ if (ds == NDMP9_DATA_STATE_HALTED) { ndmalogf (sess, 0, 2, "Operation done, cleaning up"); ndmca_monitor_get_post_backup_env (sess); return 0; } } ndmalogf (sess, 0, 0, "Operation monitoring mishandled, cancelling"); return -1; }
int ndmca_monitor_backup (struct ndm_session *sess) { struct ndm_control_agent *ca = sess->control_acb; int count; ndmp9_data_state ds; ndmp9_mover_state ms; char *estb; if (ca->job.tape_tcp) { return ndmca_monitor_backup_tape_tcp(sess); } ndmalogf (sess, 0, 3, "Monitoring backup"); for (count = 0; count < 10; count++) { ndmca_mon_wait_for_something (sess, count <= 1 ? 30 : 10); if (ndmca_monitor_get_states(sess) < 0) break; #if 0 if (count > 2) ndmca_mon_show_states(sess); #endif ds = ca->data_state.state; ms = ca->mover_state.state; estb = ndmca_data_est(ca); ndmalogf (sess, 0, 1, "DATA: bytes %lldKB%s MOVER: written %lldKB record %d", ca->data_state.bytes_processed/1024LL, estb ? estb : "", ca->mover_state.bytes_moved/1024LL, ca->mover_state.record_num); ca->job.bytes_written = ca->data_state.bytes_processed; if (ds == NDMP9_DATA_STATE_ACTIVE && ms == NDMP9_MOVER_STATE_ACTIVE) { count = 0; continue; } /* * Check MOVER for needed tape change during DATA_FLOW_TO_TAPE. * Have to do this before checking DATA. Even if DATA halted, * MOVER may be holding unwritten data. Have to perform * the tape change. */ if (ms == NDMP9_MOVER_STATE_PAUSED) { ndmp9_mover_pause_reason pr; pr = ca->mover_state.pause_reason; if (!ca->pending_notify_mover_paused) { /* count=count */ continue; /* wait for notice */ } ca->pending_notify_mover_paused = 0; ndmalogf (sess, 0, 3, "Mover paused, reason=%s", ndmp9_mover_pause_reason_to_str (pr)); /* backups are different then recoverys... When * we reach the end of a window, we signal EOW * except in V2 where we signal EOF. EOM occurs * at EOT (or EOF does). * This is based on reading comments in the email * archives... */ if ((pr == NDMP9_MOVER_PAUSE_EOM) || (pr == NDMP9_MOVER_PAUSE_EOW)) { if (ndmca_monitor_load_next(sess) == 0) { /* count=count */ continue; /* Happy */ } /* Something went wrong with tape change. */ } else if ((sess->plumb.tape->protocol_version <= 2) && pr == NDMP9_MOVER_PAUSE_EOF) { if (ndmca_monitor_load_next(sess) == 0) { /* count=count */ continue; /* Happy */ } /* Something went wrong with tape change. */ } else { /* All other pause reasons * are critically bogus. */ } ndmalogf (sess, 0, 0, "Operation paused w/o remedy, cancelling"); ndmca_mover_abort (sess); return -1; } /* * If DATA has halted, the show is over. */ if (ds == NDMP9_DATA_STATE_HALTED) { if (ms != NDMP9_MOVER_STATE_HALTED) { ndmalogf (sess, 0, 3, "DATA halted, MOVER active"); /* * MOVER still occupied. It might be a * heartbeat away from asking for another * tape. Give it a chance. */ continue; } ndmalogf (sess, 0, 2, "Operation done, cleaning up"); ndmca_monitor_get_post_backup_env (sess); return 0; } #if 1 if (ms == NDMP9_MOVER_STATE_HALTED) { if (ds == NDMP9_DATA_STATE_ACTIVE) { ndmalogf (sess, 0, 3, "MOVER halted, DATA active"); /* * DATA still occupied. */ continue; } } #endif if (ms != NDMP9_MOVER_STATE_ACTIVE && count == 0) { /* Not active. Not paused. Something wrong */ ndmalogf (sess, 0, 0, "Operation in unreasonable state, cancelling"); return -1; } } ndmalogf (sess, 0, 0, "Operation monitoring mishandled, cancelling"); return -1; }
int ndmca_monitor_recover (struct ndm_session *sess) { struct ndm_control_agent *ca = sess->control_acb; int count, rc; ndmp9_data_state ds; ndmp9_mover_state ms; char *estb; int last_state_print = 0; if (ca->job.tape_tcp) { return (ndmca_monitor_recover_tape_tcp(sess)); } ndmalogf (sess, 0, 3, "Monitoring recover"); for (count = 0; count < 10; count++) { if (ca->pending_notify_data_read) { ca->pending_notify_data_read = 0; rc = ndmca_mover_read (sess, ca->last_notify_data_read.offset, ca->last_notify_data_read.length); if (rc) { ndmalogf (sess, 0, 0, "data-read failed"); return -1; } if (count < 5) continue; } ndmca_mon_wait_for_something (sess, count <= 1 ? 30 : 10); if (ndmca_monitor_get_states(sess) < 0) break; #if 0 if (count > 2) ndmca_mon_show_states(sess); #endif ds = ca->data_state.state; ms = ca->mover_state.state; estb = ndmca_data_est(ca); if ((ds != NDMP9_DATA_STATE_ACTIVE) || (ms != NDMP9_MOVER_STATE_ACTIVE) || ((time(0) - last_state_print) >= 5)) { ndmalogf (sess, 0, 1, "DATA: bytes %lldKB%s MOVER: read %lldKB record %d", ca->data_state.bytes_processed/1024LL, estb ? estb : "", ca->mover_state.bytes_moved/1024LL, ca->mover_state.record_num); last_state_print = time(0); } ca->job.bytes_read = ca->data_state.bytes_processed; if (ds == NDMP9_DATA_STATE_ACTIVE && ms == NDMP9_MOVER_STATE_ACTIVE) { count = 0; continue; } /* * Check MOVER for needed tape change during DATA_FLOW_TO_TAPE. * Have to do this before checking DATA. Even if DATA halted, * MOVER may be holding unwritten data. Have to perform * the tape change. */ if (ms == NDMP9_MOVER_STATE_PAUSED) { ndmp9_mover_pause_reason pr; pr = ca->mover_state.pause_reason; if (!ca->pending_notify_mover_paused) { /* count=count */ continue; /* wait for notice */ } ca->pending_notify_mover_paused = 0; ndmalogf (sess, 0, 3, "Mover paused, reason=%s", ndmp9_mover_pause_reason_to_str (pr)); if (((pr == NDMP9_MOVER_PAUSE_EOF) || (pr == NDMP9_MOVER_PAUSE_SEEK)) && (ca->cur_media_ix == ca->job.media_tab.n_media)) { /* * Last tape consumed by tape agent. * The DATA agent may be just shy * of done, but there is no way for * us to tell. So, close the * image stream from the TAPE * agent side, thus indicating * EOF to the DATA agent. */ ndmalogf (sess, 0, 2, "End of tapes"); ndmca_mover_close (sess); /* count=count */ continue; } if (pr == NDMP9_MOVER_PAUSE_EOM || pr == NDMP9_MOVER_PAUSE_EOF) { if (ndmca_monitor_load_next(sess) == 0) { /* count=count */ continue; /* Happy */ } /* Something went wrong with tape change. */ } else if (pr == NDMP9_MOVER_PAUSE_SEEK) { if (ndmca_monitor_seek_tape(sess) == 0) { /* count=count */ continue; /* Happy */ } /* Something went wrong with tape change. */ } else { /* All other pause reasons * are critically bogus. */ } ndmalogf (sess, 0, 0, "Operation paused w/o remedy, cancelling"); ndmca_mover_abort (sess); return -1; } /* * If DATA has halted, the show is over. */ if (ds == NDMP9_DATA_STATE_HALTED) { if (ms != NDMP9_MOVER_STATE_HALTED) { ndmalogf (sess, 0, 3, "DATA halted, MOVER active"); /* * MOVER still occupied. It might * figure it out. Then again, it might * be awaiting a MOVER_READ. The NDMP * design does not provide a state * for awaiting MOVER_READ, so we have * to guess. */ if (count > 0) { ndmca_mover_close(sess); } continue; } ndmalogf (sess, 0, 2, "Operation done, cleaning up"); ndmca_monitor_get_post_backup_env (sess); return 0; } if (ms != NDMP9_MOVER_STATE_ACTIVE && count == 0) { /* Not active. Not paused. Something wrong */ ndmalogf (sess, 0, 0, "Operation in unreasonable state, cancelling"); return -1; } } ndmalogf (sess, 0, 0, "Operation monitoring mishandled, cancelling"); return -1; }