📄 logrec.c
字号:
/*===========================================================================*//* UTIG DMC | logrec | Logrec *//*===========================================================================*//* Name: init_logrec, open_logrec, put_logrec Purpose: SEED logical record output buffering * * this package allows output physical blocking of SEED logical records. * It supports any number of files (up to the system limit) at once. * It provides blocking and numbering services, and permits the * caller to most efficiently buffer long reads without compromising * modularity. This package is much simpler than the Unix buffering * scheme, and is oriented to SEED requirements specifcally, and * very large amounts of data. It does not have much internal consistency * checking at present.Usage: void init_logrec() int set_logrec( file, n ) struct io_buf open_logrec( file, lrecl, precl, &err ) struct io_buf close_logrec( file, &err ) struct io_buf put_logrec( file, buf, nbytes, flush, &err ) Input: Output: Externals: Warnings: Errors: Fatals: Called by: the world Calls to: sprintf, strncpy, bcopy, write Algorithm: Notes: Problems: probably not Ansi C References: Language: Sun OS 3.5 C Written: mark wiederspahn Revisions: mm/dd/yy pgmr name change 26oct89 mw change write one end of file at volume flush. we don't care if output is a disk file; ignore error. end_volume at close_logrec (not just flush_volume).*/#include <sys/types.h>#include <sys/ioctl.h>#include <sys/mtio.h>#include "output.h"struct logbuf { /* internal to logrec.c and output_data.c */ int seqno; /* sequence number last written, 0..999999 */ int lrecl; /* logical record size, 0 = no memory buffer */ int precl; /* physical record size, 0 = no memory buffer */ char *base; /* base addr of this buffer */ struct io_buf buf; /* where is it, and how much left? */ } buffer[NFILE];static struct mtop mtfunc; /* for writing eofs *//* * called once per program to initialize the logrec database * no errors are possible. */void init_logrec(){int i; for( i=0; i<NFILE; i++ ) { buffer[i].seqno = 0; buffer[i].lrecl = 0; buffer[i].precl = 0; buffer[i].base = NULL; buffer[i].buf.len = 0; buffer[i].buf.addr = NULL; }}/* * called to set the sequence number ( n >= 0 ) or * get its current value ( n < 0 ); always returns * current value if no error */int set_logrec( file, n )FILE *file; /* file pointer */int n; /* sequence number, or -1 */{ if( fileno(file) >= 0 && fileno(file) < NFILE ) { if( n >= 0 ) buffer[fileno(file)].seqno = n; return( buffer[fileno(file)].seqno ); } else { return( -1 ); }} /* * called once per file to allocate memory and set up pointers * errors: * if returned io_buf.addr == NULL, and io_buf.len = 0 * the file was bad, lrecl or precl make no sense, (err=2) * or no buffer space could be obtained (err=1). */struct io_buf open_logrec( file, lrecl, precl, err )FILE *file; /* open file */int lrecl; /* logical record length */int precl; /* physical record length */int *err; /* error status: * 0 = ok * 1 = get memory failed * 2 = calling args illegal */{struct io_buf bad; bad.addr = NULL; /* return junk if really bad params */ bad.len = 0; if( fileno(file) >= 0 && fileno(file) < NFILE && lrecl > 512 && lrecl < 8192 && /* see SEED doc */ precl > 512 && precl < 65536 && /* phys limit of mt */ precl%lrecl == 0 && precl/lrecl >= 1 ) /* must fit evenly */ { if( (buffer[fileno(file)].base = buffer[fileno(file)].buf.addr = (char *)malloc(precl)) == NULL ) { *err = 1; return( bad ); /* no memory */ } else { *err = 0; /* success */ buffer[fileno(file)].lrecl = lrecl; buffer[fileno(file)].precl = buffer[fileno(file)].buf.len = precl; return( buffer[fileno(file)].buf ); } } else *err = 2; return( bad ); /* bad input */}/* * close out a logical record stream. This routine flushes the file, * and also writes an eof mark on tapes only. */struct io_buf close_logrec( file, err )FILE *file; /* open file pointer */int *err; /* return status */{struct io_buf result; /* return me if bad file */ result.addr = NULL; /* return junk if really bad params */ result.len = 0; if( fileno(file) >= 0 && fileno(file) < NFILE ) { result = put_logrec( file, NULL, 0, 2, err ); free( buffer[fileno(file)].base ); buffer[fileno(file)].base = buffer[fileno(file)].buf.addr = NULL; buffer[fileno(file)].precl = buffer[fileno(file)].lrecl = buffer[fileno(file)].buf.len = 0; *err = 0; return( buffer[fileno(file)].buf ); /* success */ } else { *err = 1; return( result ); /* failure */ }}/* * called to output a logical record. The number of contiguous bytes * is in "nbytes", which may be zero. This serves as an inital request * to obtain the best location to read data into to minimize data movement. * * flushing the volume writes one end of file on tapes. */struct io_buf put_logrec( file, buf, nbytes, flush, err )FILE *file; /* open output file */char *buf; /* source of data to be output */int nbytes; /* number of bytes in buf to output */int flush; /* flag for type of flushing, if any: * 0 = no flush to be done. nbytes must be mod lrecl * 1 = flush out physical record buffer with noise * 2 = flush physical record, plus end volume (eof?) */int *err; /* return status code: * 0 = all ok * ? = failure */{int len; /* lengths of various things */int fd; /* file descriptor, index into buffer data */register char *p; /* fast fill pointer */struct io_buf bad; /* return me if bad file */char digits[7]; /* temp digit string */static int bytes_so_far = 0; bad.addr = NULL; /* return junk if really bad params */ bad.len = 0;/* * if the file pointer is bogus, do nothing */ fd = fileno(file); if( fd >= 0 && fd < NFILE ) {/* * if there is no physical record buffer, die an immediate death */ if( buffer[fd].base == NULL ) { *err = 1; return( buffer[fd].buf ); }/* * Now that the worst mistakes are past us, assume no further errors. * if there is possibly anything to move, determine how much and do it */ *err = 0; if( nbytes >= 0 ) { len = nbytes; if( len > buffer[fd].buf.len ) len = buffer[fd].buf.len; if( len > 0 && buf != buffer[fd].buf.addr ) bcopy( buf, buffer[fd].buf.addr,len ); /* buffer[fd].lrecl = Lrecl; *//* * for each logical record, put the sequence number in */ while( len > 0 ) { if ((bytes_so_far % Lrecl) == 0) buffer[fd].seqno++; bytes_so_far += buffer[fd].lrecl; sprintf( digits, "%.6d", buffer[fd].seqno ); strncpy( buffer[fd].buf.addr, digits, 6 ); len -= buffer[fd].lrecl; buffer[fd].buf.len -= buffer[fd].lrecl; buffer[fd].buf.addr += buffer[fd].lrecl; }/* * if we are flushing, fill logical records with spaces, and datatype = space; * even noise records get proper sequence numbers. However, if the physical * record buffer is completely empty, do no flush at all. */ if( flush > 0 ) { if( buffer[fd].buf.len != buffer[fd].precl ) { while( buffer[fd].buf.len > 0 ) { p = buffer[fd].buf.addr; len = buffer[fd].lrecl; while( len-- ) *p++ = SPACE; if ((bytes_so_far % Lrecl) == 0) buffer[fd].seqno++; bytes_so_far += buffer[fd].lrecl; sprintf( digits, "%.6d", buffer[fd].seqno ); strncpy( buffer[fd].buf.addr, digits, 6 ); len -= buffer[fd].lrecl; buffer[fd].buf.len -= buffer[fd].lrecl; buffer[fd].buf.addr += buffer[fd].lrecl; } } }/* * if the physical record is full, output it now, and show empty phys buffer */ if( buffer[fd].buf.len <= 0 ) { if( write( fd, buffer[fd].base, buffer[fd].precl ) < 0) *err = 2; buffer[fd].buf.len = buffer[fd].precl; buffer[fd].buf.addr = buffer[fd].base; memset(buffer[fd].base, ' ', buffer[fd].precl); }/* * if we are volume flushing a non-empty volume, write an eof */ if( flush == 2 && buffer[fd].seqno != 0 ) { mtfunc.mt_op = MTWEOF; mtfunc.mt_count = 1; ioctl( fd, MTIOCTOP, &mtfunc ); } } return( buffer[fd].buf ); } else { *err = 3; /* return for bad fd */ return( bad ); } }/* ----------------------------------------------------------------------- */struct io_buf flush_buff( file, len)FILE *file; /* open output file */int len;{ int fd; /* file descriptor, index into buffer data */ int num_bytes_left; char wrkstr[100];/* * if the file pointer is bogus, do nothing */ fd = fileno(file); if( fd >= 0 && fd < NFILE ) { } if(write(fd, buffer[fd].base, buffer[fd].buf.addr - buffer[fd].base) < 0) { sprintf(wrkstr, "flush_buff: bad write!"); error_handler(WARNING, wrkstr); } buffer[fd].buf.len = buffer[fd].precl; buffer[fd].buf.addr = buffer[fd].base; memset(buffer[fd].base, ' ', buffer[fd].precl); return(buffer[fd].buf); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -