⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tapedrive.c

📁 Solaris环境下的数据挖掘算法:birch聚类算法。该算法适用于对大量数据的挖掘。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  This file contributed by the Tape Join project and modified locally.  See attached copyright notice.*//*  $Id: tapedrive.C,v 1.15 1996/12/03 20:24:58 jussi Exp $  $Log: tapedrive.C,v $  Revision 1.15  1996/12/03 20:24:58  jussi  Renamed preprocessor flags.  Revision 1.14  1996/11/23 21:33:35  jussi  Fixed some bugs when compiled with PROCESS_TASK.  Revision 1.13  1996/10/02 15:24:02  wenger  Improved error handling (modified a number of places in the code to use  the DevError class).  Revision 1.12  1996/09/26 18:55:42  jussi  Added support for 64-bit file offsets. Tape commands are now  executed in a subprocess or thread which increases parallelism  in the system.  Revision 1.11  1996/07/18 02:48:24  jussi  Make this code compile in Ultrix.  Revision 1.10  1996/07/12 00:55:39  jussi  Updated copyright information to reflect original source.  Revision 1.9  1996/06/27 16:04:25  jussi  Added a cast in memchr() so that the code compiles cleanly in Linux.  Revision 1.8  1996/04/16 20:56:25  jussi  Replaced assert() calls with DOASSERT macro.  Revision 1.7  1996/01/13 03:22:51  jussi  Removed #include <tar.h> -- this is in tapedrive.h.  Revision 1.6  1995/12/28 17:50:00  jussi  Small fixes to remove new compiler warnings.  Revision 1.5  1995/11/09 22:23:28  jussi  Added debugging statements.  Revision 1.4  1995/10/31 17:13:17  jussi  Added tar archive handling routines and data structures.  Revision 1.3  1995/09/22 15:46:22  jussi  Added copyright message.  Revision 1.2  1995/09/05 20:31:56  jussi  Added CVS header.*//*  Copyright 1993-1996 by Jussi Myllymaki    Permission to use, copy, modify, and distribute this software and its  documentation for any purpose and without fee is hereby granted,  provided that the above copyright notice appear in all copies and that  both that copyright notice and this permission notice appear in  supporting documentation, and that the name(s) of the copyright holder(s)  not be used in advertising or publicity pertaining to distribution of  the software without specific, written prior permission. The copyright  holder(s) make no representations about the suitability of this  software for any purpose.  It is provided "as is" without express  or implied warranty.    Author: Jussi Myllymaki*///#define TAPE_DEBUG//#define TAPE_DEBUG2#include <iostream.h>#include <unistd.h>#include <string.h>#include "tapedrive.h"#include "DCE.h"#include "Exit.h"#include "DevError.h"// Use fake fileno and blkno to make this file compile in Alpha// until a real fix is found. The problem is that in Alpha/OSF,// struct mtget (mtio.h) does not include fields mt_fileno and// mt_blkno. See warning printed out below.#if defined(__alpha) || defined(__ultrix)#define mt_fileno mt_resid * 0#define mt_blkno  mt_resid * 0#endif#define USE_FWRITEBUF//#define USE_FREADchar *TapeDrive::_mt_op_name[] = { "WEOF", "FSF", "BSF", "FSR",                                   "BSR", "REW", "OFFL", "NOP",                                   "RETEN", "ERASE", "EOM", "NBSF",                                   "SRSZ", "GRSZ", "LOAD" };TapeDrive::TapeDrive(char *name, char *mode, int fno, int blockSz) :	initialized(0), fileNo(fno), blockSize(blockSz),	haveTarHeader(0), tarFileSize(0), tarFileOffset(0){#if defined(__alpha) || defined(__ultrix)  cerr << "Warning: In Ultrix and Alpha/OSF/1, file number and block number"       << endl;  cerr << "         inquiry does not work. TapeDrive will probably fail."       << endl;#endif  _child = 0;  if (!(file = fopen(name, mode))) {    reportErrSys("fopen");    return;  }#ifdef USE_FWRITEBUF  // fwrite() in flushBuffer() will write 8 kB blocks to tape even  // if we request larger blocks; we have to force it to use  // the specified block size  int fwriteBufSize = blockSize + 8;  _fwriteBuf = new char [fwriteBufSize];  DOASSERT(_fwriteBuf, "Out of memory");  if (setvbuf(file, _fwriteBuf, _IOFBF, fwriteBufSize) != 0) {      reportErrSys("setvbuf");      exit(1);  }#endif#if 0  setbuf(file, 0);#endif  atEof = (mode[0] == 'w');  for(unsigned int i = 0; i < _max_mt_op; i++)    mt_tim[i] = mt_ios[i] = mt_cnt[i] = 0;  read_time = read_ios = read_cnt = 0;  write_time = write_ios = write_cnt = 0;  // If the caller gave us the 'target' file number, let's use it.  // If no number was given, use the current file on the tape.  if (fileNo < 0) {    getStatus();    fileNo = tstat.mt_fileno;  }  gotoBeginningOfFile();  buffer = new char [blockSize];  DOASSERT(buffer, "Out of memory");  bufferType = readBuffer;  bufferBlock = 0;  bufferOffset = 0;  bufferBytes = 0;  initialized = 1;}TapeDrive::~TapeDrive(){  if (!initialized)    return;  if (bufferType == writeBuffer)    flushBuffer();  delete buffer;  waitForChildProcess();  setbuf(file, 0);  if (fclose(file))    reportErrSys("fclose");#ifdef USE_FWRITEBUF  delete _fwriteBuf;#endif}void TapeDrive::printStats(){  cout << "Tape usage statistics:" << endl;  cout << "  cmd\tcalls\tcount\tavgtime" << endl;  for(unsigned int i = 0; i < _max_mt_op; i++) {    if (mt_ios[i] > 0) {      cout << "  " << _mt_op_name[i]           << "\t" << mt_ios[i]           << "\t" << mt_cnt[i]	   << "\t" << mt_tim[i] / (mt_cnt[i] ? mt_cnt[i] : 1) << endl;    }  }  cout << "  read\t" << read_ios << "\t" << read_cnt       << "\t" << read_time / (read_ios ? read_ios : 1) << endl;  cout << "  write\t" << write_ios << "\t" << write_cnt       << "\t" << write_time / (write_ios ? write_ios : 1) << endl;}void TapeDrive::readTarHeader(){  DOASSERT(!haveTarHeader, "Invalid tar header flag");  int bytes = read(&tarHeader, sizeof tarHeader);  DOASSERT(bytes == sizeof tarHeader, "Invalid tar header size");  tarFileSize = oct2int(tarHeader.dbuf.size);  tarFileOffset = 0;  TAPEDBG(cout << "Read tar header: " << tarHeader.dbuf.name << ", size "	  << tarFileSize << endl);  haveTarHeader = 1;}unsigned long int TapeDrive::oct2int(char *buf){  unsigned long int num = 0;  while(*buf == ' ') buf++;  while(*buf != ' ')    num = 8 * num + (*buf++ - '0');  return num;}void TapeDrive::waitForChildProcess(){  if (_child > 0) {    TAPEDBG(cout << "Waiting for tape " << fileno(file)            << " to become idle" << endl);#ifdef TAPE_THREAD    (void)pthread_join(_child, 0);#else    while(1) {        int status;        pid_t child = wait(&status);        if (child < 0) {            if (errno == EINTR)                continue;            if (errno != ECHILD) {                reportErrSys("wait");                exit(1);            }        } else            break;    }#endif    TAPEDBG(cout << "Tape " << fileno(file) << " has become idle" << endl);    _child = 0;  }}long long TapeDrive::seek(long long offset){  TAPEDBG(cout << "Seek to offset " << offset << " of tape "          << fileno(file) << endl);  DOASSERT(offset >= 0, "Invalid tape offset");  if (bufferType == writeBuffer) {      // flush out write buffer    flushBuffer();    bufferType = readBuffer;    bufferBlock = 0;  }  long long lblock = offset / blockSize;  long long loff = offset % blockSize;  long block = lblock;  long off = loff;  TAPEDBG(cout << "Seeking to lblock " << lblock << ", block "          << block << " of tape " << fileno(file) << endl);  if (block != bufferBlock - 1) {       // not current block?    gotoBlock(block);                   // goto new block location    fillBuffer();                       // read it into buffer  }  bufferBlock = block + 1;              // on tape, just past current block  bufferOffset = off;  if (bufferOffset > bufferBytes) {    cerr << "Seeking past end of file" << endl;    exit(1);  }  return offset;}int TapeDrive::read(void *buf, int recSize, int binary){  TAPEDBG2(cout << "Read request for " << recSize << " "           << (binary ? "binary" : "ASCII")           << " bytes to " << (void *)buf << endl);  if (bufferType != readBuffer) {    cerr << "Must do a seek before switching from writing to reading" << endl;    exit(1);  }  DOASSERT(bufferOffset >= 0 && bufferOffset <= blockSize,	   "Inconsistent data");  DOASSERT(bufferBytes >= 0 && bufferBytes <= blockSize, "Inconsistent data");  DOASSERT(bufferOffset <= bufferBytes, "Inconsistent data");#ifdef TARFILESIZE  if (haveTarHeader                     // is file in a tar archive?      && tarFileOffset >= tarFileSize)  // and at end of file?    atEof = 1;#endif  if (atEof)                            // already at end of tape file?    return 0;  if (bufferOffset >= bufferBytes) {    // no more bytes in buffer?    fillBuffer();                       // get next block from file    if (!bufferBytes) {                 // end of file?#ifdef TARFILESIZE      // for non-tar files, end of tape file is the natural end of      // user file; for tar files, the file size indicated in the      // tar header should trigger the atEof statement a few lines      // up; it is an error if the tape file (tar file) ends before      // the file inside the tar file      if (haveTarHeader)	cerr << "File in tar archive prematurely terminated." << endl;#endif      return 0;    }  }  read_cnt++;  if (read_cnt % 1000 == 0)    TAPEDBG2(cout << read_cnt << " " << flush);#ifdef TAPE_BLOCK_PADDING  char *start = buffer + bufferOffset;        // starting point for this record  DOASSERT(*start != 0, "Unexpected record"); // must not be an empty record  if (recSize > bufferBytes - bufferOffset)    recSize = bufferBytes - bufferOffset;#ifdef TARFILESIZE  if (haveTarHeader                     // past EOF of file in tar archive?      && recSize > tarFileSize - tarFileOffset)    recSize = tarFileSize - tarFileOffset;#endif  if (!binary) {                        // reading an ASCII record?    char *end = (char *)memchr(start, 0, recSize);    DOASSERT(end, "End of record not found");    recSize = end - start;              // do not include record separator  }  TAPEDBG2(cout << "Copying " << recSize << " bytes to "           << (void *)buf << endl);  memcpy(buf, start, recSize);  bufferOffset += recSize + 1;          // go past record separator too  if (!binary                           // in ASCII mode?      && bufferOffset < bufferBytes     // still data left but...      && !buffer[bufferOffset]))        // last record in block?    bufferOffset = bufferBytes;         // must fetch new block next time#else  int bytesLeft = recSize;#ifdef TARFILESIZE  if (haveTarHeader                     // past EOF of file in tar archive?      && bytesLeft > tarFileSize - tarFileOffset)    bytesLeft = tarFileSize - tarFileOffset;#endif  recSize = 0;  char *p = (char *)buf;  while(bytesLeft > 0) {    char *start = buffer + bufferOffset;    int b = bufferBytes - bufferOffset; // bytes left in buffer    if (bytesLeft < b)                  // caller doesn't want that many?      b = bytesLeft;    char *end = 0;    if (!binary) {                      // reading an ASCII record?      end = (char *)memchr((void *)start, '\n', b);      if (end)                          // found newline = end of record?	b = end - start + 1;    }    TAPEDBG2(cout << "Copying " << b << " bytes to " << (void *)p << endl);    memcpy(p, start, b);    bufferOffset += b;    bytesLeft -= b;    recSize += b;    p += b;    if (end)                            // found newline = end of record?      break;    if (bufferOffset >= bufferBytes)    // need next block?      fillBuffer();    if (!bufferBytes)                   // end of physical file?      break;  }  if (!binary                           // in ASCII mode?      && bufferOffset < bufferBytes     // still data left but...      && !buffer[bufferOffset])         // end of logical file (NULL char)?    bufferOffset = bufferBytes;         // must try to fetch block next time#endif#ifdef TARFILESIZE  if (haveTarHeader) {     tarFileOffset += recSize;     DOASSERT(tarFileOffset <= tarFileSize, "Inconsistent data");  }#endif  return recSize;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -