/* @(#)tz6.c 17.1.1.1 (ESO-DMD) 01/25/02 17:36:46 */ /*=========================================================================== Copyright (C) 1995 European Southern Observatory (ESO) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. Correspondence concerning ESO-MIDAS should be addressed as follows: Internet e-mail: midas@eso.org Postal address: European Southern Observatory Data Management Division Karl-Schwarzschild-Strasse 2 D 85748 Garching bei Muenchen GERMANY ===========================================================================*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .TYPE Module .NAME TZ6.C .LANGUAGE C .AUTHOR J.D.Ponz IPG-ESO Garching .CATEGORY table interface (Design 2.0) low level routines. .COMMENTS This module contains the lower level routines handling tables: read/write consecutive pieces of data. \begin{TeX} There are basically three access modes: \begin{enumerate} \item Mapping access: The complete file is mapped. This can be forced in TCTOPN / TCTINI routines with the F\_MAP\_FORCE option. \item Elementary access (i/o): only what is required is read in a buffer. The maximal number of buffers is the configuration TBL\_TBUFS \item Simulated mapping \end{enumerate} \end{TeX} .VERSION 1.0 25-Mar-1987 Implementation JDP .VERSION 1.1 16-Jan-1989 Include handling of record file organization .VERSION 3.0 01-Jul-1990 New Version with Arrays / Elementary IO .VERSION 3.1 27-Sep-1990 Added TBL_UMAP (Unmap a region) .VERSION 3.2 29-Apr-1991: Better management ot EIO mode .VERSION 3.3 06-Jun-1991: Corrected mapped flags in eload .VERSION 3.4 27-JAN-92 CORRECT FLAG IN ELOAD FOR MAPPING OF BIG TABLES ------------------------------------------------------------*/ #include /* General MIDAS Symbols */ #include /* Table System parameters */ #include /* List of Table Errors */ #include /* General-use Macros */ static int status = 0; /* Can be retrieved via TBL_RDst*/ static unsigned char masks[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; char *osmmget(); /*======================================================================= * Internal Routines *=======================================================================*/ #ifdef __STDC__ static int write_buffer (TABLE *tp, TABLE_BUF *bp) #else static int write_buffer (tp, bp) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Write to associated file the specified buffer .RETURNS Status (!=0 if fails) .REMARKS Only useful in EIO (elementay i/o) mode. -------------------------------------------------------------*/ TABLE *tp; /* IN: Table concerned */ TABLE_BUF *bp; /* MOD: The buffer concerned */ #endif { int status; status = ERR_NORMAL; if (!bp->buf) return(status); if (bp->flags & TBL__MODIFIED) status = SCFPUT (tp->imno, 1 + bp->offset, bp->used, (char *)bp->buf); /* Free the allocated space */ if (status) TBL_errf(status, "writing table %s (EIO mode)", tp->phname); else { osmmfree ((char *)bp->buf); tp->sbuf -= bp->size; oscfill ((char *)bp, sizeof(TABLE_BUF), 0); /* Zero freed buffer */ } return(status); } #ifdef __STDC__ static int write_nonmapped (TABLE *tp, TABLE_BUF *bp) #else static int write_nonmapped (tp, bp) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Write to associated file the buffer, ONLY if NON-Mapped .RETURNS Status (!=0 if fails) .REMARKS Only useful in EIO (elementay i/o) mode. -------------------------------------------------------------*/ TABLE *tp; /* IN: Table concerned */ TABLE_BUF *bp; /* MOD: The buffer concerned */ #endif { if_not (bp->flags & TBL__MAPPED && tp->tflags & TBL__MODIFIED) return(write_buffer(tp, bp)); TBL_errf(ERR_TBLMAP, "overlap of mapped zone(s) in table: %s", tp->phname); return (ERR_TBLMAP); } #ifdef __STDC__ static char *load (TABLE *tp, int offset, int len, int flag) #else static char *load (tp, offset, len, flag) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Load len bytes into a table, starting at offset. .RETURNS Where data loaded (tp->addres + offset) / NULL if fails .REMARKS Only useful simulated mapping mode. -------------------------------------------------------------*/ TABLE *tp; /* IN: Table concerned */ int offset; /* IN: starting point */ int len; /* IN: How many bytes */ int flag; /* IN: not-zero for write */ #endif { int mask; int i, byte, bit0, bit1, read_items; /* Transform offset into buffer */ bit0 = offset >> TBL_LOG2BUF; bit1 = (offset+len-1) >> TBL_LOG2BUF; status = ERR_NORMAL; /* Load required buffers if necessary */ for (i = bit0; (status == ERR_NORMAL) && (i <= bit1); i++) { byte = i >> 3; mask = masks[i&7]; if (tp->loaded_map[byte] & mask) ; else { status = SCFGET (tp->imno, 1+i*TBL_BUFITEMS, TBL_BUFITEMS, &read_items, tp->addres + (i<loaded_map[byte] |= mask; } if (flag) { /* do not set flag if only reading (KB 000901) */ if (tp->tflags & TBL__READONLY) ; else tp->modified_map[byte] |= mask; } } if (status) TBL_errf(status, "reading table %s (MAP mode)", tp->phname); return(tp->addres + offset); } #ifdef __STDC__ static char *eload (TABLE *tp, int offset, int len, int flag) #else static char *eload (tp, offset, len, flag) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Elementary Load len bytes into a table, starting at offset. .RETURNS Where data was loaded .REMARKS Only useful in EIO (elementay i/o) mode. -------------------------------------------------------------*/ TABLE *tp; /* IN: Table concerned */ int offset; /* IN: starting point */ int len; /* IN: How many bytes */ int flag; /* IN: 1 for Write, 2 for Map */ #endif { TABLE_BUF ab, *abp, *bp, *hbp; int upper, lower, w0, w1; int W0, W1; int i; char can_load_more; /* Fill the `running' buffer */ tp->iocount += 1; ab.iocount = tp->iocount; abp = &ab; status = ERR_NORMAL; /* w0 & w1 are the lower & upper bounds of the zone. W0 & W1 are the lower & upper bounds rounded for best i/o upper & lower are limits of the loaded zone being examined can_load_more is a flag used to enlarge the read */ /* Scan buffers for THE buffer */ /* Starting point = previously found buffer */ w0 = offset >> 2; w1 = (offset+len-1) >> 2; W0 = (w0 >> (TBL_LOG2BUF-2)) << (TBL_LOG2BUF-2); W1 = ((w1 >> (TBL_LOG2BUF-2)) << (TBL_LOG2BUF-2)) |(TBL_BUFITEMS-1); can_load_more = (flag != TBL__MAPPED); /* Find out whether buffer is already loaded */ hbp = tp->tbuf + tp->nbuf; /* Highest buffer */ bp = tp->tbuf + tp->cbuf; /* Current buffer */ for (i = tp->nbuf; --i >= 0; bp++){ if (bp == hbp) bp = tp->tbuf; choose_oldest: if (status != ERR_NORMAL) break; if (bp->iocount < abp->iocount) abp = bp; if (!bp->buf) continue; lower = bp->offset; upper = lower + bp->size - 1; if (w0 >= lower) { if (w1 <= upper){ /* Asked zone included in buffer */ if_not (flag & TBL__MAPPED) goto found_buffer; if (w0 == lower && w1 == upper) goto found_buffer; if (bp->flags & TBL__MAPPED) goto found_buffer; } if (w0 > upper) { /* Asked zone following buffer */ if(W0 <= upper) can_load_more = 0; continue; } status = write_nonmapped(tp, bp); goto choose_oldest; } if (w1 < lower) { if (W1 >= lower) can_load_more = 0; continue; } status = write_buffer (tp, bp); goto choose_oldest; } if (status) return((char *)0); bp = abp; if (bp->buf) { if (bp->flags & TBL__MAPPED) { /* Must expand EIO Buffers */ i = tp->nbuf + TBL_TBUFS; TBL_errf(-1, "Expand Number of Mapped Buffers to %d", tp->nbuf); tp->tbuf = (TABLE_BUF *)osmmexp((char *)tp->tbuf, i*sizeof(TABLE_BUF)); bp = abp = tp->tbuf + tp->nbuf; oscfill ((char *)bp, TBL_TBUFS*sizeof(TABLE_BUF), 0); tp->nbuf = i; } else status = write_buffer (tp, bp); if (status) return((char *)0); } /* Allocate & Load the buffer */ found_buffer: if (!bp->buf) { bp->offset = (can_load_more ? W0 : w0); bp->size = 1 + (can_load_more ? W1-W0 : w1 - w0); /* Must rewrite buffers if not enough space */ upper = (TBL_EIO_LIMIT >> 2) - bp->size; for (i = tp->nbuf, abp = tp->tbuf; (--i >= 0) && (tp->sbuf > upper); abp++) { if (!abp->buf) continue; if (abp->flags & TBL__MAPPED) continue; status = write_buffer (tp, abp); if (status) return((char *)0); } /* bp->buf = (int *)osmmget (sizeof(long) * bp->size);*/ bp->buf = (int *)osmmget (sizeof(int) * bp->size); if (!bp->buf) { TBL_errf(ERR_TBLMAP,"mapping table %s for %d elements", tp->phname, bp->size); return((char *)0); } tp->sbuf += bp->size; status = SCFGET (tp->imno, 1+bp->offset, bp->size, &bp->used, (char *)bp->buf); if (status) { TBL_errf(status, "reading table %s (EIO mode)", tp->phname); return((char *)0); } } bp->iocount = tp->iocount; /* Flag loaded + Modified */ bp->flags |= flag; if (flag == 1) bp->flags |= TBL__MODIFIED; tp->cbuf = (bp - tp->tbuf); /* Current buffer */ return((char *)(bp->buf + w0 - bp->offset)); } /*======================================================================= * Public Routines *=======================================================================*/ int TBL_WR(tp) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Physically write the modified parts of the table .RETURNS Status ------------------------------------------------------------------*/ TABLE *tp; /* MOD: Table concerned */ { int status, mask; int i, len, bit1; TABLE_BUF *bp; status = ERR_NORMAL; if (tp->tflags & TBL__MAPPED) return(status); if (tp->tflags & TBL__EIO) { /* Elementary Mode */ for (i = tp->nbuf, bp = tp->tbuf; (status == ERR_NORMAL) && (--i >= 0); bp++) status = write_buffer (tp, bp); return(status); } /* Simulated Map Mode */ bit1 = tp->wsize >> (TBL_LOG2BUF - 2); for (i=0, mask=0x80; (status == ERR_NORMAL) && (i <= bit1); i++) { if (tp->modified_map[i>>3] & mask) { len = (i < bit1 ? TBL_BUFITEMS : tp->wsize & (TBL_BUFITEMS-1)); status = SCFPUT (tp->imno, 1 + (i << (TBL_LOG2BUF-2)), len, tp->addres + (i<>= 1; if (!mask) mask = 0x80; } if (status) TBL_errf(status, "writing table %s (MAP mode)", tp->phname); return (status); } int TBL_RDst () /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Retrieve the status of the last encountered error in TBLRD / TBDRDF .RETURNS Status (0 for OK) -------------------------------------------------------------*/ { return(status); } char *TBL_RD (tp, offset, len) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Check len bytes in a table, starting at offset, are loaded .RETURNS Pointer to table of specified offset / NULL if fails -------------------------------------------------------------*/ TABLE *tp; /* IN: Table concerned */ int offset; /* IN: starting point */ int len; /* IN: How many bytes */ { char *p; /* NOTE: status is set up by load / eload */ /* Which Access Mode ? */ if (tp->tflags & TBL__MAPPED) return (tp->addres + offset); if (tp->tflags & TBL__EIO) { p = eload(tp, offset, len, 0); p += offset - ((offset >> 2) << 2); } else p = load (tp, offset, len, 0); return (p); } char *TBL_RDF (tp, offset, len, flag) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Check len bytes in a table, starting at offset, are loaded. Set MODIFIED flag. .RETURNS Pointer to table of specified offset / NULL if fails -------------------------------------------------------------*/ TABLE *tp; /* IN: Table concerned */ int offset; /* IN: starting point */ int len; /* IN: How many bytes */ int flag; /* IN: Flag 1 (Write) / 2 (Map) */ { char *p; char errview[100]; /* If file is mapped, don't care about modifications! */ if (tp->tflags & TBL__MAPPED) return (tp->addres + offset); if (flag == 1 && tp->usname) { sprintf(errview,"Unable to write in view: %s",tp->usname); SCTPUT(errview); SCSEPI(); } if ((tp->tflags & TBL__READONLY)&&(flag !=2)) flag = 0; if (flag == 2 && tp->tflags & TBL__READONLY) ; else if (flag) tp->tflags |= TBL__MODIFIED; if (tp->tflags & TBL__EIO) { p = eload(tp, offset, len, flag); p += offset - ((offset >> 2) << 2); } else p = load (tp, offset, len, flag); return (p); } int TBL_UMAP (tp, addr) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Unmap a buffer that was previously mapped. .RETURNS Status as 0 (OK) / -1 (Was not mapped) / Other error -------------------------------------------------------------*/ TABLE *tp; /* IN: Table concerned */ char *addr; /* IN: Address to Unmap */ { TABLE_BUF *bp; int i, status; if (! addr) return(0); /* NULL is OK */ status = -1; /* Default if buffer not found */ for (i = tp->nbuf, bp = tp->tbuf; --i >= 0; bp++){ if ((char *)bp->buf == addr) { status = write_buffer(tp, bp); break; /* Only one can exist.. */ } } return (status); }