📄 server.c
字号:
tapefd = -1; tapeaccessmode = NOT_OPEN; return(ret);}Int32write_tape_buffer(Int32 * bufferpos, Int32 * bytes_flushed){ Int32 nextidx, r; if(streamerbuffer){#ifdef HAVE_POSIX_THREADS /* prevent other thread from reconfiguring */ pthread_mutex_lock(&may_reconfig_buffer_mutex); /* the buffer */ pthread_mutex_lock(&may_modify_buffer_ptrs);#endif nextidx = streamerbuf_insert_idx + 1; if(nextidx >= streamerbufferlen) nextidx = 0;#ifdef HAVE_POSIX_THREADS if(nextidx == streamerbuf_processed_idx){ /* let other thread process */ streamerbuf_writing = YES; /* not really necessary, if highmark */ /* is set reasonably */ pthread_mutex_unlock(&may_reconfig_buffer_mutex); if(buffer_thread_running) pthread_cond_wait(&can_write_to_buffer, /* wait for space */ &may_modify_buffer_ptrs); pthread_mutex_lock(&may_reconfig_buffer_mutex); nextidx = streamerbuf_insert_idx + 1; /* buffer might have been */ if(nextidx >= streamerbufferlen) /* reconfigured */ nextidx = 0; }#else while(nextidx == streamerbuf_processed_idx){ process_tape_ops(NO, YES); if(tapefd < 0 && (tapeaccessmode & OPENED_RAW_ACCESS)) return(WRITE_FAILED); }#endif memcpy(streamerbuffer + streamerbuf_insert_idx * tapeblocksize, tapebuffer, sizeof(UChar) * tapeblocksize); streamerbuf_insert_idx = nextidx; *bytes_flushed = tapeblocksize; *bufferpos = 0;#ifdef HAVE_POSIX_THREADS if(num_blocks_in_streamerbuf >= streamerbuf_highmark){ streamerbuf_writing = YES; pthread_cond_signal(&buffer_contains_data); } pthread_mutex_unlock(&may_modify_buffer_ptrs); pthread_mutex_unlock(&may_reconfig_buffer_mutex); if(tapefd < 0 && (tapeaccessmode & OPENED_RAW_ACCESS)) return(-errno);#endif return(0); } else{ if(iauxtapebuffer){ Int32 i, iauxbufpos, iauxbytes_in_tapefile; for(i = r = 0; i < iauxtapebufferlen; i += tapeblocksize){ r = flush_buffer_to_tape(iauxtapebuffer + i, &iauxbufpos, &iauxbytes_in_tapefile); if(r || iauxbufpos != 0 || iauxbytes_in_tapefile != tapeblocksize){ r = (r ? r : FATAL_ERROR); break; } } ZFREE(iauxtapebuffer); iauxtapebufferlen = 0; if(r) return(r); } return(flush_buffer_to_tape(tapebuffer, bufferpos, bytes_flushed)); }}/* write tapebuffer to tape, evtl. start a new file or change cartridge */Int32flush_buffer_to_tape( UChar *tapebuf, Int32 *bufferpos, /* only to return the new value */ Int32 *flushed_bytes){ static Flag write_error = NO; Int32 i, newcart, newfile, written, w, ret = NO_ERROR; Int32 cart_bef_change, files_on_tape; UChar *filename; Flag eom, do_reopen = NO, dont_write = NO; int filemode; filenum_incr_by_eof = NO; files_on_tape = actfilenum; if(!(tapeaccessmode & OPENED_RAW_ACCESS)){ if(maxbytes_per_tape && bytes_on_tape + (Real64) tapeblocksize > maxbytes_per_tape[actcart - 1]){ eom = YES; statusmsg(T_("Current cartridge no. %d is already full\n"), (int) actcart); goto change_tape; /* sorry, otherwise huge complication */ } if(maxbytes_per_file && bytes_in_tapefile + tapeblocksize > maxbytes_per_file){ do_reopen = YES; } if(streamerbuffer){ if(reqnewfilebuf[streamerbuf_processed_idx]){ if(bytes_in_tapefile > 0) /* only reopen, if nothing has been */ do_reopen = YES; /* written to the current tape file yet */ reqnewfilebuf[streamerbuf_processed_idx] = NO; } } else{ if(newfilerequested){ if(bytes_in_tapefile > 0) /* same as above */ do_reopen = YES; newfilerequested = NO; } } if(do_reopen){ if(reopentapewr()){ logmsg(LOG_ERR, T_("Error: Cannot reopen device for writing.\n")); ret = REOPEN_FAILED; GETOUT; } files_on_tape = actfilenum; } } errno = 0; /* set errno unconditionally here, cause return values */ /* on FreeBSD below are different compared to other OSes */ /* so errno must be evaluated to and thus be reset here */ written = write_forced(tapefd, tapebuf, tapeblocksize); w = (written > 0 ? written : 0); bytes_in_tapefile += w; bytes_on_tape += (Real64) w; /* status report */ write_rate += w; if(!write_meas_time){ write_meas_time = time(NULL); write_rate = 0; } else{ actime = time(NULL); if(actime >= write_meas_time + 10){ statusmsg(T_("Device %s is writing with %d KB/s to cartridge %d, file %d.\n"), (char *) devicename, (int)((((write_rate >> 9) + 1) >> 1) / (actime - write_meas_time)), (int) actcart, (int) actfilenum); write_meas_time = actime; write_rate = 0; } } *flushed_bytes = w; if(written == tapeblocksize){ /* the normal case */ write_error = NO; *bufferpos = 0; tape_rewound = NO; tape_moved = YES; return(0); } if(written > 0 && written < tapeblocksize){ /* block not fully written */ memmove(tapebuf, tapebuf + written, (tapeblocksize - written) * sizeof(UChar)); *bufferpos = written; /* we try not to be afraid */ write_error = NO; return(0); } if(tapeaccessmode & OPENED_RAW_ACCESS){ /* In raw access mode */ if(tapefd >= 0) /* it is always an error, */ close(tapefd); /* if nothing could be written */ tapefd = -1; *bufferpos = 0; return(ENDOFTAPEREACHED); }#ifdef __FreeBSD_version#if __FreeBSD_version >= 470000#define FREE_BSD_470000_OR_HIGHER 1#endif#endif#ifdef FREE_BSD_470000_OR_HIGHER /* hooray, the FreeBSD 'SA' driver behaviour has changed with */ /* FreeBSD 4.7 towards one closer to System-V style. Sigh. */ /* Modification suggested and tested by Rudolf Cejka at */ /* Brno University of Technology */ eom = (written == 0) ? YES : NO; if(written < 0){ /* tape operation failed */#else eom = NO; if(written <= 0){ /* tape operation failed */#endif i = errno; /* this assignment is for debugging purposes */#ifdef sun if(!END_OF_TAPE(errno)){ /* on full filesystem END_OF_TAPE is true */ struct mtget mtstat; /* so here we get only with tapes */ i = ioctl(tapefd, MTIOCGET, &mtstat); if(i){ logmsg(LOG_ERR, T_("Error: Cannot get tape status after write failure.\n")); errno = ENOSPC; } else{ if(mtstat.mt_erreg) /* mt_erreg is UNDOCUMENTED, even on Sun- */ errno = ENOSPC; /* solve. So we assume end of tape on any */ } /* error != 0 */ } /* suspicions are: 0x13==EOT, 0x12==EOF, 0x05==illegal-req */ /* 0x08==blank-check(EOR) */#endif#if defined(__hpux) || defined(hpux)#ifdef MTIOCGET if(!END_OF_TAPE(errno)){ /* on full filesystem END_OF_TAPE is true */ struct mtget mtgetst; /* so here we get only with tapes */ i = ioctl(tapefd, MTIOCGET, &mtgetst); if(i){ logmsg(LOG_ERR, T_("Error: Cannot get tape status after write failure.\n")); errno = ENOSPC; } else{ if(GMT_EOT(mtgetst.mt_gstat)) /* see man 7 mt on HPUX */ errno = ENOSPC; } /* error != 0 */ }#endif#endif if(END_OF_TAPE(errno)){ eom = YES; errno = 0; } else if(errno ==#ifdef _AIX EMEDIA || errno == #endif EIO){ if(write_error){ logmsg(LOG_ERR, T_("Error: Repeated faults writing to tape, now: %s.\n"), strerror(errno)); ret = FATAL_ERROR; GETOUT; } logmsg(LOG_WARNING, T_("Warning: A media error occured (%d), trying to reposition and reopen.\n"), errno); files_on_tape = actfilenum;#if 0 /* this may not be done here, cause by definition tapeaccessmode */ tapeaccessmode = NOT_OPEN; /* reflects the status seen by the */#endif /* client regardless of server internal problems. */ /* tapeaccessmode = NOT_OPEN will be set if recovery is impossible */ if(tapefd >= 0) /* streamers usually rewind on an EIO, e.g. */ close(tapefd); /* due to a SCSI bus reset. It would not be */ /* a cool idea to simply */ tapefd = -1; /* reopen and write on, */ i = (bytes_in_tapefile > 0 ? 1 : 0); /* thus overwriting stuff */ if(set_filenum(actfilenum + i, NO, NO)) /* written before. So we */ eom = YES; /* try to re-position to the next file. If */ else /* that fails, we load the next cartridge. */ files_on_tape = actfilenum; /* If the current tapefile is still */ /* empty, reposition to the same */ write_error = YES; } else{ logmsg(LOG_ERR, T_("Error: Writing to tape: %s.\n"), strerror(errno)); ret = FATAL_ERROR; GETOUT; } } if(!eom){ i = reopentapewr(); /* try again into the next tape file */ if(!i){ files_on_tape = actfilenum; errno = 0; /* see above for comment */ written = write_forced(tapefd, tapebuf, tapeblocksize); w = (written > 0 ? written : 0); bytes_in_tapefile += w; bytes_on_tape += (Real64) w; write_rate += w; /* for status report */ *flushed_bytes = w; if(written == tapeblocksize){ /* that worked */ write_error = NO; *bufferpos = 0; tape_moved = YES; tape_rewound = NO; return(0); } if(written > 0 && written < tapeblocksize){ memmove(tapebuf, tapebuf + written, (tapeblocksize - written) * sizeof(UChar)); *bufferpos = written; /* keep fingers crossed */ write_error = NO; return(0); } eom = YES; /* some other problems with the tape, assume EOM */ logmsg(LOG_WARNING, T_("Warning: An unexpected error (%d) occured, changing cartridge. Proceeding with fingers crossed.\n"), errno); write_error = YES; } else{ /* reopen failed */ logmsg(LOG_WARNING, T_("Warning: Reopen failed (%d), changing cartridge. Proceeding with fingers crossed.\n"), errno); eom = YES; } } change_tape: if(eom){ /* TAPE FULL */ if(tapefd >= 0) close(tapefd); /* we change the cartridge and try again */ tapefd = -1; tape_full_actions(actcart); if( (i = save_bytes_per_tape_msg(bytesontape_file, actcart, bytes_on_tape, files_on_tape, YES, time(NULL))) ){ ret = REOPEN_FAILED; GETOUT; } if(interrupted) do_exit(1); bytes_in_tapefile = 0; endofrec = NO; if(!AUTOCHCART) return(ENDOFTAPEREACHED); cart_bef_change = actcart; i = find_next_free_pos(&newcart, &newfile, inscart[active_cartset], active_cartset); if(i){ logmsg(LOG_ERR, T_("Error: Cannot find a new cartridge for writing.\n")); ret = REOPEN_FAILED; GETOUT; } i = set_cartridge(- newcart, YES); /* a clone tape is accepted here */ if(i){ /* only after repeated tries */ logmsg(LOG_ERR, T_("Error: Cannot change to cartridge %d for writing.\n"), newcart); ret = REOPEN_FAILED; GETOUT; } /* now actcart is newcart is tape in drive */ if(actcart != newcart && var_append) /* other cartridge inserted */ newfile = insfilenum[active_cartset]; i = save_cart_order(cart_bef_change, actcart, newfile); if(i){ /* this is no longer done in find_next_free_pos */ ret = REOPEN_FAILED; GETOUT; } if(newfile == 1) bytes_on_tape = 0.0; else i = get_bytes_per_tape_msg(bytesontape_file, actcart, &bytes_on_tape, NULL, NULL, NULL); if(newfile == 1){ i = rewindtape(YES, NO); actfilenum = 1; } else i = set_filenum(newfile, YES, NO); if(i){ logmsg(LOG_ERR, T_("Error: Cannot move to file %d for writing.\n"), (int) newfile); ret = i; GETOUT; }#ifdef HAVE_POSIX_THREADS if(streamerbuffer) pthread_mutex_lock(&tapepos_mutex);#endif inscart[active_cartset] = rdcart = actcart; insfilenum[active_cartset] = rdfilenum = actfilenum;#ifdef HAVE_POSIX_THREADS if(streamerbuffer) pthread_mutex_unlock(&tapepos_mutex);#endif if(actcart != newcart && !var_append) logmsg(LOG_CRIT, T_("Internal Error: Wrong tape %d accepted in drive for %d, please report.\n"), actcart, newcart); if(actfilenum != newfile) logmsg(LOG_CRIT, T_("Internal Error: Wrong file number %d set instead of %d, please report.\n"), actfilenum, newfile); if(interrupted) do_exit(1); add_to_written_tapes(actcart /* == newcart */); if(newfile == 1){ i = erasetape(); if(i) logmsg(LOG_WARNING, T_("Warning: Cannot erase tape.\n")); if(interrupted) do_exit(1); if(newfile == 1){ i = rewindtape(YES, NO); actfilenum = 1; } else i = set_filenum(newfile, YES, NO); if(i){ logmsg(LOG_ERR, T_("Error: Cannot move to file %d for writing.\n"), (int) newfile); ret = i; GETOUT; } } if(interrupted) do_exit(1); if(inscart[active_cartset] != actcart /* == newcart */) logmsg(LOG_CRIT, T_("Internal Error: Wrong tape for writing in drive, please report.\n")); if(actfilenum == 1){ i = write_infobuffer(inscart[active_cartset] /* == newcart */); if(i){ logmsg(LOG_ERR, T_("Error: Cannot write label to tape.\n")); ret = i; GETOUT; } insfilenum[active_cartset] = actfilenum = 1; } if(write_tapepos_file_msg()){ ret = REOPEN_FAILED; GETOUT; } if( (i = save_bytes_per_tape_msg(bytesontape_file, actcart, bytes_on_tape, actfilenum, NO, time(NULL))) ){ ret = REOPEN_FAILED; GETOUT; } if(IS_REGFILE(devstatb) || IS_DIRECTORY(devstatb)){ if( (i = update_devicesettings(insfilenum[active_cartset], YES)) ){ logmsg(LOG_ERR, T_("Error: Cannot change to file %d for writing.\n"), insfilenum[active_cartset]); ret = i; GETOUT; } } filename = devicename; filemode = O_WRONLY | O_BINARY; if(IS_DIRECTORY(devstatb)){ filename = storefile; filemode = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -