/* @(#)midldb.c 17.1.1.1 (ESO-DMD) 01/25/02 17:36:24 */ /*=========================================================================== 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 ===========================================================================*/ /*+++++++++++++++++++++ Module MIDLDB +++++++++++++++++++++++++++++++++++++++ .LANGUAGE C .IDENTIFICATION Module MIDLDB .AUTHOR Klaus Banse ESO - Garching .KEYWORDS Local Descriptor Blocks .ENVIRONMENT VMS and UNIX .COMMENTS holds cacheLDB, CRELDB, LDBinfo, RDLDB, WRLDB .VERSIONS [1.30] 861110: move from FORTRAN to C 010911 last modif ------------------------------------------------------------------------*/ #include #include #define BIT_0 0x1 #define NOLDB 4 /* */ int cacheLDB(flag,chanl,blockno,lp) /*++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE create a local descriptor block (LDB) = 4 virtual blocks .ALGORITHM create + initialize a LDB for a bulk data frame if the present block points to another (LDB_NEXT != 0) then one already exists. otherwise, the logical file extent is incremented and the file physically extended, if necessary .RETURNS status: I*4 return status --------------------------------------------------*/ int flag; /* IN: = 0, clear entry 1, read 2, write 22, create fresh LDB 3, close out (force writing) */ int chanl; /* IN: I/O channel */ int blockno; /* IN: virtual block no. */ struct LDB_STRUCT **lp; /* OUT: pointer to LDB */ { int fifo, found, status; register int nr, *ireg; char *cldb; struct LDB_STRUCT *ldbp; static int lastout = 0; static int chanLDB[NOLDB], blkLDB[NOLDB]; static int statLDB[NOLDB]={0,0,0,0,}; /* sync with NOLDB !! */ static struct LDB_STRUCT KLDB[NOLDB]; /* statLDB = 0: free = 1: read LDB = 2: marked for writing */ if (flag == 0) { for (nr=0; nr= NOLDB) lastout = 0; } else { found = fifo; /* use free entry */ cldb = (char *) &KLDB[found]; goto last_step; } update: cldb = (char *) &KLDB[found]; if (statLDB[found] > 1) { status = OSY_WVB(chanLDB[found],cldb,2048,blkLDB[found]); if (status != ERR_NORMAL) return status; } /* statLDB updated below */ last_step: chanLDB[found] = chanl; blkLDB[found] = blockno; *lp = &KLDB[found]; if (flag != 22) { status = OSY_RVB(chanl,cldb,2048,blockno); statLDB[found] = 1; return status; } /* create a "fresh" LDB */ init_LDB: statLDB[found] = 2; ldbp = &KLDB[found]; ldbp->BLKNUM = blockno; ldbp->NEXT = 0; ireg = ldbp->LDBWORDS.IWORD; for (nr=0; nrIOCHAN; fcbp = fctpntr->FZP; /* if another LDB exists, write the present one to disk + read the next */ if (ldbp->NEXT != 0) { vbn = ldbp->BLKNUM; status = cacheLDB(2,chanl,vbn,&ldbp); /* save LDB */ if (status == ERR_NORMAL) status = cacheLDB(1,chanl,ldbp->NEXT,&ldbp); /* get next one */ if (status == ERR_NORMAL) return status; /* that's it already folks ... */ else goto end_of_it; } /* We have to get a new "block" - may be already allocated also increment logical file extension. If logical ext. greater than physical ext., extend data frame */ blockno = fcbp->LEXBDF + 4; /* LDB = 4 blocks */ if (fcbp->LEXJMP == 'Y') { fcbp->LEXJMP = ' '; /* only used once */ fcbp->LEXBDF = fcbp->PEXBDF; blockno = fcbp->LEXBDF + 4; } if (blockno > fcbp->PEXBDF) { /* extend frame for additional descr. blocks (LDBs) */ int exalq; /* printf("CRELDB: blockno = %d, fcbp->PEXBDF = %d\n",blockno,fcbp->PEXBDF); */ if (chanl < 0) /* we have a "memory file" */ { exalq = 32; /* increase by 8 LDBs */ status = MID_VMEM(2,exalq,&chanl); /* extend virtual memory */ if (status != ERR_NORMAL) { MID_ERROR("FSY","MID_CRELDB",status,0); return status; /* status = ERR_MEMOUT */ } fcbp->PEXBDF += exalq; } else { exalq = 16; /* increase by 4 LDBs */ #if vms FSY_EXTBDF(fctpntr->FILEIDA,fctpntr->FILEIDB,fctpntr->DEVICE, exalq,&lpex,&status); #else FSY_EXTBDF(fctpntr->FILEID,exalq,&lpex,&status); #endif if ( (status & BIT_0) == 0 ) { MID_ERROR("FSY","MID_CRELDB/FSY_EXTBDF",status,0); return ERR_FRMNAC; } fcbp->PEXBDF = lpex; } } /* update existing LDB + write it to disk */ ldbp->NEXT = fcbp->LEXBDF + 1; status = cacheLDB(3,chanl,ldbp->BLKNUM,&ldbp); /* force writing */ if (status != ERR_NORMAL) goto end_of_it; /* initialize new LDB */ status = cacheLDB(22,chanl,ldbp->NEXT,&ldbp); if (status != ERR_NORMAL) goto end_of_it; fcbp->LEXBDF = blockno; /* update FCB.LEXBDF */ return status; /* something wrong - report it */ end_of_it: MID_ERROR("MIDAS","MID_CRELDB:",status,0); return status; } /* */ void LDBinfo(chanl,ldbp,indx,alen,extens) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Get header info (i.e. next extension) of an atom from the local descriptor block, (LDB = 4 virtual blocks) .ALGORITHM Each atom in the LDB is preceded by a header of 3 longwords. The 1. longword holds the no. of data elements in that atom The 2. holds the block no.of next extension. If = -1, no extension exists. The 3. holds the index of next extension Ojo: the code must be synchronised with the "header section" of the following MID_RDLDB routine !!! .RETURNS nothing -------------------------------------------------------------------------*/ int chanl /* IN : channel no. of frame */; struct LDB_STRUCT *ldbp; /* IN: points to LDB */ int indx /* IN : word # in LDB, where atom is to be read */; int *alen /* IO : no. of values required, will be set to actual length \ of atom starting from pos. 1 specified via first \ if = 0, only the header will be returned */; int *extens /* OUT: block no. + indx of next extension */; { int status; /* get 1. header longword = actual length */ *alen = ldbp->LDBWORDS.IWORD[indx]; /* get 2. header longword */ if (indx >= LDB_NDSCRW1) { status = cacheLDB(1,chanl,ldbp->NEXT,&ldbp); indx = -1; /* so indx will be 0 */ } *extens = ldbp->LDBWORDS.IWORD[++indx]; /* that's the next extension */ /* get 3. header longword */ if (indx >= LDB_NDSCRW1) { status = cacheLDB(1,chanl,ldbp->NEXT,&ldbp); indx = -1; /* so indx will be 0 */ } /* the index of next extension */ *(extens+1) = ldbp->LDBWORDS.IWORD[++indx]; } /* */ void MID_RDLDB(chanl,ldbp,indx,typ,iatom,ratom,catom,first,alen,extens) /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE read an atom from the local descriptor block, LDB = 4 virtual blocks .ALGORITHM Each atom in the LDB is preceded by a header of 3 longwords. The 1. longword holds the no. of data elements in that atom The 2. holds the block no.of next extension. If = -1, no extension exists. The 3. holds the index of next extension Ojo: the code of the "header section" must be synchronised with the routine LDBinfo above !!! .RETURNS nothing -------------------------------------------------------------------------*/ int chanl /* IN : channel no. of frame */; struct LDB_STRUCT *ldbp; /* IN: points to LDB */ int indx /* IN : word # in LDB, where atom is to be read */; int typ /* IN : type of atom 1=I*4, 2=R*4, 3=character */; int *iatom /* OUT: receives integer atom */; float *ratom /* OUT: receives real atom */; char *catom /* OUT: receives character atom */; int first /* IN : 1st position of descriptor data to be accessed */; int *alen /* IO : no. of values required, will be set to actual length \ of atom starting from pos. 1 specified via first \ if = 0, only the header will be returned */; int *extens /* OUT: block no. + indx of next extension */; { int felem, rlen, fcharm1; int left, slen, from, status; register char *goal, *now; rlen = *alen; /* get 1. header longword = actual length */ *alen = ldbp->LDBWORDS.IWORD[indx]; /* get 2. header longword */ if (indx >= LDB_NDSCRW1) { status = cacheLDB(1,chanl,ldbp->NEXT,&ldbp); indx = -1; /* so indx will be 0 */ } *extens = ldbp->LDBWORDS.IWORD[++indx]; /* that's the next extension */ /* get 3. header longword */ if (indx >= LDB_NDSCRW1) { status = cacheLDB(1,chanl,ldbp->NEXT,&ldbp); indx = -1; /* so indx will be 0 */ } /* the index of next extension */ *(extens+1) = ldbp->LDBWORDS.IWORD[++indx]; /* this check left in for backwards compatibility and should be taken out one day... */ if (rlen < 1) return; /* we just wanted the next extension*/ /* for character data, split offset into longwords + bytes */ if (typ == 3) { felem = (first-1)/II_SIZE ; fcharm1 = first - (felem*II_SIZE) - 1; felem ++ ; } else felem = first; *alen -= (first - 1); /* increment indx + read next LDB, if necessary */ indx += felem; while (indx > LDB_NDSCRW1) { status = cacheLDB(1,chanl,ldbp->NEXT,&ldbp); indx -= LDB_NDSCRW; } /* indx is now in [0,509] - initialize counters */ if (*alen > rlen) *alen = rlen; /* total length to be transmitted */ else rlen = *alen; from = 0; /* branch according to 'typ' */ more_data: left = LDB_NDSCRW - indx ; /* no. of lw's left */ slen = left; if (typ == 1) /* integer atom */ { register int *result, *ireg; if (rlen < left) slen = rlen; /* transfer in this blockno */ result = iatom + from; ireg = ldbp->LDBWORDS.IWORD + indx; goal = (char *) result; now = (char *) ireg; (void) memcpy(goal,now,(size_t)(slen*II_SIZE)); indx += slen; } else if (typ == 2) /* real atom */ { register float *result, *rreg; if (rlen < left) slen = rlen; /* transfer in this blockno */ result = ratom + from; rreg = ldbp->LDBWORDS.RWORD + indx; goal = (char *) result; now = (char *) rreg; (void) memcpy(goal,now,(size_t)(slen*RR_SIZE)); indx += slen; } else { /* character atom */ register char *cpntra, *cpntrb; left = left*II_SIZE - fcharm1; if (rlen > left) slen = left; else slen = rlen; cpntra = (char *)&(ldbp->LDBWORDS); cpntra += (indx*II_SIZE + fcharm1); /* point to first char. */ cpntrb = catom + from; (void) memcpy(cpntrb,cpntra,(size_t)slen); fcharm1 = 0; /* now we are always at a longword boundary */ indx += (slen+(II_SIZE-1))/II_SIZE ; } /* read next LDB, if necessary */ if (indx > LDB_NDSCRW1) { status = cacheLDB(1,chanl,ldbp->NEXT,&ldbp); indx = 0; } if (rlen > slen) { rlen -= slen; from += slen; goto more_data; /* get more data */ } } /* */ void MID_WRLDB(chanl,ldbp,indx,typ,iatom,ratom,catom,conflg,first,alen,extens) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE write into an existing atom in the LDB (only the data is updated) and return atom length (in data values) and next extension of atom .ALGORITHM Each atom in the LDB is preceded by a header of three 4-byte words The 1. word holds the length of the atom in data elements, the 2. holds the block no. of next extension. If = -1, no extension exists. the 3. holds the indx of next extension .RETURNS nothing -------------------------------------------------------------------------*/ int chanl /* IN : channel no. of frame */; struct LDB_STRUCT *ldbp; /* IN: points to LDB */ int indx /* IN : index in current LDB */; int typ /* IN : type of atom 1=I*4, 2=R*4, 3=character data */; int *iatom /* IN : contains integer atom */; char *catom /* IN : contains character atom */; float *ratom /* IN : contains real atom */; int conflg /* IN : constant flag = 1 (yes), 0 = (no) */; int first /* IN : position of descriptor data to be accessed */; int *alen /* IO : no. of values required will be set to actual no. of \ values modified, starting from 1st position specified \ via first */; int *extens /* IO : returns block + indx of extension */; { int felem, rlen, fcharm1; int left, slen, from, status; register int nr; register char *goal, *now; rlen = *alen; /* get 1. header 4-byte word = actual length */ *alen = ldbp->LDBWORDS.IWORD[indx]; /* get 2. header 4-byte words */ if (indx >= LDB_NDSCRW1) { status = cacheLDB(1,chanl,ldbp->NEXT,&ldbp); indx = -1; /* so indx will be 0 */ } /* that's the next extension */ *extens = ldbp->LDBWORDS.IWORD[++indx]; /* get 3. header 4-byte words */ if (indx == LDB_NDSCRW1) { status = cacheLDB(1,chanl,ldbp->NEXT,&ldbp); indx = -1; /* so indx will be 0 */ } /* indx of next extension */ *(extens+1) = ldbp->LDBWORDS.IWORD[++indx]; /* for character data, split offset into (integer) 4-byte words + bytes */ if (typ == 3) { felem = (first-1)/II_SIZE ; fcharm1 = first - (felem*II_SIZE) - 1; felem ++ ; } else felem = first; *alen -= (first - 1); /* increment indx + read next LDB, if necessary */ indx += felem; while (indx > LDB_NDSCRW1) { status = cacheLDB(1,chanl,ldbp->NEXT,&ldbp); indx -= LDB_NDSCRW; } /* indx is now in [0,509] - initialize counters */ if (*alen > rlen) *alen = rlen; /* total length to be transmitted */ else rlen = *alen; from = 0; /* branch according to data type */ more_data: left = LDB_NDSCRW - indx ; /* no. of int's left */ slen = left; /* check for each type for constant flag */ if (typ == 1) /* integer atom */ { register int *source, *ireg; if (rlen < left) slen = rlen; /* transfer in this blockno */ source = iatom + from; ireg = ldbp->LDBWORDS.IWORD + indx; if (conflg == 1) { register int ival; ival = *source; for (nr=0;nrLDBWORDS.RWORD + indx; if (conflg == 1) { register float rval; rval = *source; for (nr=0;nr left) slen = left; else slen = rlen; cpntra = (char *) &(ldbp->LDBWORDS); cpntra += (indx*II_SIZE + fcharm1); /* point to first char. */ cpntrb = catom + from; if (conflg == 1) { register char cval; cval = *cpntrb; for (nr=0;nrBLKNUM,&ldbp); if (indx > LDB_NDSCRW1) { status = cacheLDB(1,chanl,ldbp->NEXT,&ldbp); indx = 0; } if (rlen > slen) { rlen -= slen; from += slen; goto more_data; /* write more data */ } }