/* @(#)tz8.c 17.1.1.1 (ES0-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 Massachusetss Ave, Cambridge, MA 02139, USA. Corresponding 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 TZ8.C .LANGUAGE C .AUTHOR J.D.Ponz IPG-ESO Garching .CATEGORY table interface, low level routines. .KEYWORDS Overflow mechanism. .COMMENTS This module contains the lower level routines handling tables. Column and row overflow mechanism in either record or transposed formats. TBL_ALLOCOL(tid, nc) TBL_ALLOROW(tid, nr) TBL_ADDROW(tid,irow,nr) TBL_DELROW(tid,irow,nr) .VERSION 1.0 25-Mar-1987 Definition JDP .VERSION 1.1 17-Jan-1989 Include record file organization .VERSION 1.2 25-May-1990 Correct bug in TBL_ALLROW MP .VERSION 3.0 01-Jul-1990 New Version with Arrays / Elementary IO .VERSION 3.1 03-Dec-1990 Check table number did not change. ------------------------------------------------------------*/ #include /* General MIDAS Symbols */ #include /* Table System parameters */ #include /* Symbols used for Tables */ #include /* List of Table Errors */ #include /* Classical macros */ /*======================================================================= * Public Routines *=======================================================================*/ TBL_ALLOCOL(tid, nc) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Allocate extra column(s) when no physical space is available. The routine restructures the table file. .ALGORITHM Save old table parameters, allocate new columns in an output table, copy all table data, copy table descriptors, close input and output tables, delete input table file, rename output table file, open this table again. .RETURNS Status -------------------------------------------------------------*/ int tid /* IN: table identifier */; int nc /* IN: number of words per record to be allocated */; { TABLE *tp, *tn; int status; int new_tid, i, j, len, offset; char *source, *dest; char table_name[TBL_NAMLEN+1]; tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if (nc <= tp->acols) return (TBL_errf(ERR_TBLCOL, "expand columns to too small number %d, table: %s", nc, tp->phname)); if (tp->swise != F_TRANS) if_not(source = TBL_RD (tp, 0, 4*tp->wsize)) return(TBL_RDst()); if (tp->usname) return(TBL_errf(ERR_TBLFUL, "can't expand view %s", tp->usname)); else if (tp->tflags & TBL__READONLY) return(TBL_errf(ERR_TBLFUL, "can't expand read-only table %s", tp->phname)); /* display warning message */; /* TBL_errf(0, "expand to %d columns table: %s", nc, tp->phname); */ /* allocate new table file; note that mode = number of columns << 16 + mode */ if (!(nc&1)) nc++; /* Odd number of Columns */ i = MAX (tp->colitems, TBL_DALCOL) ; if (tp->swise == F_TRANS) i = (i << 16) | (F_O_MODE|F_ALL_FORCE); else i = (i << 16) | (F_O_MODE|F_MAP_FORCE|F_ALL_FORCE); if (status = TCTINI(TBL_tmpname, tp->swise, i, nc, tp->arows, &new_tid)) return(status); tn = TBL_ptr(new_tid); /* copy descriptors */; if (status = SCDCOP(tp->imno, tn->imno, 1, " ")) return(TBL_errf(status, "(in column expansion)")); /* Copy those descriptors that will be rewritten by TCTCLO */ for (j = 0; j < tp->colitems; j++) tn->dtypes[j] = tp->dtypes[j]; for (j = 0; j < tp->colitems; j++) tn->offset[j] = tp->offset[j]; tn->cols = tp->cols; tn->rows = tp->rows; tn->kcol = tp->kcol; tn->scol = tp->scol; tn->swise = tp->swise; tn->version= tp->version; tn->selected = tp->selected; /* copy data */ len = tp->reclen; /* Length of 1 record */ dest = tn->addres; if (tp->swise == F_TRANS) { offset = 0; i = 4*tp->wsize; while (i > 0) { len = MIN(TBL_EIO_LIMIT/2,i); source = TBL_RDF(tp,offset,len,0); dest = TBL_RDF(tn,offset,len,1); oscopy (dest, source, len); i -= len; offset+=len; } } else { for (i = tp->arows; --i >= 0; source += len, dest += tn->reclen) oscopy (dest, source, len); } /* it is not required to initialize the data in the columns, this will be done when the columns are defined */ /* rename table file */; if (status = MID_RETNAM(tp->imno, table_name, sizeof(table_name))) return(TBL_errf(status, "(in column expansion)")); if (status = TCTCLO(tid)) return(status); if (status = TCTCLO(new_tid)) return(status); if (status = SCFDEL(table_name)) return(TBL_errf(status, "(in column expansion)")); if (status = SCFRNM(TBL_tmpname, table_name)) return(TBL_errf(status, "(in column expansion)")); new_tid = tid; /* Tell that we want to keep the Old Number */ status = TCTOPN(table_name, F_IO_MODE, &new_tid); if ((status == ERR_NORMAL) && (new_tid != tid)) SCTPUT("++++ Table Number Changed!"); return (status); } TBL_ALLOROW(tid, nr) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Allocate extra row(s) when no physical space is available. The routine restructures the table file. .ALGORITHM Save old table parameters, allocate new rows in an output table, copy all table data, copy table descriptors, close input and output tables, delete input table file, rename output table file, open this table again. .RETURNS Status -------------------------------------------------------------*/ int tid /* IN: table identifier */; int nr /* IN: number of rows to be allocated */; { TABLE *tp, *tn; int status; int new_tid, i, j, len, dtype, new_rows; char *source0, *source, *dest; char table_name[TBL_NAMLEN+1]; tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); if_not(source0 = TBL_RD (tp, 0, 4*tp->wsize)) return(TBL_RDst()); if (nr <= tp->arows) return (TBL_errf(ERR_TBLROW, "expand tow to too small value %d, table: %s", nr, tp->phname)); if (tp->tflags & TBL__READONLY) return(TBL_errf(ERR_TBLFUL, "can't expand read-only table %s", tp->phname)); /* display warning message */; /* TBL_errf(0, "expand to %d rows table: %s", nr, tp->phname); */ /* allocate new table file */; nr = ( (nr+7)>>3)<<3; /* Multiple of 8 */ i = MAX (tp->colitems, TBL_DALCOL) ; i = (i << 16) | (F_O_MODE|F_MAP_FORCE|F_ALL_FORCE); if (status = TCTINI(TBL_tmpname, tp->swise, i, tp->acols, nr, &new_tid)) return(status); tn = TBL_ptr(new_tid); /* copy descriptors */; if (status = SCDCOP(tp->imno, tn->imno, 1, " ")) return(TBL_errf(status, "(in row expansion)")); /* Copy those descriptors that will be rewritten by TCTCLO */ for (j = 0; j < tp->colitems; j++) tn->dtypes[j] = tp->dtypes[j]; for (j = 0; j < tp->colitems; j++) tn->offset[j] = tp->offset[j]; tn->cols = tp->cols; tn->rows = tp->rows; tn->kcol = tp->kcol; tn->scol = tp->scol; tn->swise = tp->swise; tn->version= tp->version; /* copy data */; new_rows = tn->arows - tp->arows; if (tp->swise == F_TRANS) { for (j=0; j<= tp->cols; j++) { source = source0 + TBL_offset (tp, 1, j); dest = tn->addres + TBL_offset (tn, 1, j); len = tp->arows * (j ? tp->bytes[j-1] : sizeof(int)); oscopy (dest, source, len); dest += len; if (j == 0) for (i = new_rows; --i >= 0; dest += sizeof(int)) *(int *)dest = 1; else { len = ColumnWidth(tp, j); dtype = ColumnType (tp, j); for (i = new_rows; --i >= 0; dest += len) TBL_toNULL (dtype, dest); } } } else { /* Record organisation */ source = source0; dest = tn->addres; len = tp->reclen * tp->arows; oscopy (dest, source, len); i = tp->arows + 1; dest = tn->addres + TBL_offset (tn, i, 0); * (int *)dest = 1; source = dest; for (j=1; j<= tp->cols; j++) { dest = tn->addres + TBL_offset (tn, i, j); TBL_toNULL (ColumnType(tn, j), dest); } i++; dest = tn->addres + TBL_offset (tn, i, j); len = tn->reclen; while (i++ < tn->arows) dest += oscopy (dest, source, len); } /* rename table file */; if (status = MID_RETNAM(tp->imno, table_name, sizeof(table_name))) return(TBL_errf(status, "(in row expansion)")); if (status = TCTCLO(tid)) return(status); if (status = TCTCLO(new_tid)) return(status); if (status = SCFDEL(table_name)) return(TBL_errf(status, "(in row expansion)")); if (status = SCFRNM(TBL_tmpname, table_name)) return(TBL_errf(status, "(in row expansion)")); new_tid = tid; /* Tell that we want to keep the Old Number */ status = TCTOPN(table_name, F_IO_MODE, &new_tid); if ((status == ERR_NORMAL) && (new_tid != tid)) SCTPUT("++++ Table Number Changed!"); return (status); } TBL_ADDROW(tid,irow,nr) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Add row(s) .ALGORITHM Save old table parameters, allocate new rows in an output table, copy all table data, copy table descriptors, close input and output tables, delete input table file, rename output table file, open this table again. .RETURNS Status -------------------------------------------------------------*/ int tid; /* IN: table identifier */ int irow; /* IN: position at which rows should be created */ int nr; /* IN: number of rows to be created */ { char *source0,*source,*dest; char table_name[TBL_NAMLEN+1]; TABLE *tp,*tn; int new_tid; int dtype; int newrow; int i ,j , k , status, len; tp = TBL_ptr(tid); if (status = CheckTable(tp)) { return(TBL_errs(tid, status,0)); } if_not(source0 = TBL_RD (tp, 0, 4*tp->wsize)) return(TBL_RDst()); if (irow > tp->rows) { return(ERR_TBLROW); } i = MAX(tp->colitems,TBL_DALCOL); i = (i << 16) | (F_O_MODE|F_MAP_FORCE|F_ALL_FORCE); /* SCTPUT("Allocate new table file with newrow = rows + nr rows\n"); */ newrow = ((tp->rows+nr+7)>>3)<<3; /* SCTPUT("Initialization of selection flag\n"); */ status = TCTINI(TBL_tmpname, tp->swise, i, tp->acols, newrow, &new_tid); if (status != 0) return(status); tn = TBL_ptr(new_tid); /* SCTPUT("Copy descriptors from one frame to another\n"); */ status = SCDCOP(tp->imno, tn->imno, 1, " "); if (status != 0) return(TBL_errf(status, "(in row expansion)")); for (j=0; jcolitems; j++) { tn->dtypes[j] = tp->dtypes[j]; } for (j=0; jcolitems; j++) { tn->offset[j] = tp->offset[j]; } tn->cols = tp->cols; /* no. of columns */ tn->rows = tp->rows + nr; /* no. of rows */ tn->kcol = tp->kcol; /* Reference col */ tn->scol = tp->scol; /* sorted column number */ tn->swise = tp->swise; tn->version = tp->version; tn->selected = tp->rows + nr; /* selected rows = all rows */ /* this was missing PN 12/98*/ /* SCTPUT("Copy data\n"); */ for (j=0; j<= tp->cols; j++) /* copy data */ { source = source0 + TBL_offset(tp,1,j); dest = tn->addres + TBL_offset(tn,1,j); len = irow * (j ? tp->bytes[j-1] : sizeof(int)); oscopy(dest,source,len); dest +=len; if (j == 0) { for (i = nr; --i>=0; dest += sizeof(int)) { *(int *)dest = 1; } } else { len = ColumnWidth(tp,j); dtype = ColumnType (tp, j); for (i = nr; --i >=0; dest +=len) { TBL_toNULL(dtype,dest); } } source += irow * (j ? tp->bytes[j-1] : sizeof(int)); len = (tp->rows - irow) * (j ? tp->bytes[j-1] : sizeof(int)); oscopy(dest,source,len); } /* SCTPUT("Rename table file\n");*/ status = MID_RETNAM(tp->imno, table_name, sizeof(table_name)); if (status != 0) return(TBL_errf(status, "(in row expansion)")); /*close old and new table*/ if (status = TCTCLO(tid)) return(status); if (status = TCTCLO(new_tid)) return(status); if (status = SCFDEL(table_name)) return(TBL_errf(status, "(in row expansion)")); if (status = SCFRNM(TBL_tmpname, table_name)) return(TBL_errf(status, "(in row expansion)")); new_tid = tid; /* Tell that we want to keep the Old Number */ status = TCTOPN(table_name, F_IO_MODE, &new_tid); if ((status == ERR_NORMAL) && (new_tid != tid)) { SCTPUT("++++ Table Number Changed!"); } return (status); /*end of TBL_ADDROW*/ } /*-----------------------------------------------------------------*/ TBL_DELROW(tid,irow,nr) /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .PURPOSE Delete row(s) .ALGORITHM Save old table parameters, allocate new rows in an output table, copy all table data, copy table descriptors, close input and output tables, delete input table file, rename output table file, open this table again. .RETURNS Status -------------------------------------------------------------*/ int tid; /* table id */ int irow; /* row number where rows should be deleted */ int nr; /* number of rows to be deleted */ { char *source0,*source,*dest; char table_name[TBL_NAMLEN+1]; TABLE *tp,*tn; int new_tid, dtype, newrow; int i ,j , k , status, len; tp = TBL_ptr(tid); if (status = CheckTable(tp)) return(TBL_errs(tid, status,0)); for (i=irow; i tp->rows) return(ERR_TBLROW); if_not(source0 = TBL_RD (tp, 0, 4*tp->wsize)) return(TBL_RDst()); i = MAX(tp->colitems,TBL_DALCOL); i = (i << 16) | (F_O_MODE|F_MAP_FORCE|F_ALL_FORCE); /* SCTPUT("Allocate new table file with newrow = rows - nr rows\n"); */ newrow = ((tp->rows-nr+7)>>3)<<3; if (status = TCTINI(TBL_tmpname, tp->swise, i, tp->acols, newrow, &new_tid)) return(status); tn = TBL_ptr(new_tid); if (status = SCDCOP(tp->imno, tn->imno, 1, " ")) return(TBL_errf(status, "(in row expansion)")); for (j=0; jcolitems; j++) tn->dtypes[j] = tp->dtypes[j]; for (j=0; jcolitems; j++) tn->offset[j] = tp->offset[j]; tn->cols = tp->cols; tn->rows = tp->rows - nr; tn->kcol = tp->kcol; tn->scol = tp->scol; tn->swise = tp->swise; tn->version = tp->version; tn->selected = tn->rows; /* no. of selected rows equals no. of rows */ for (j=0; j<= tp->cols; j++) /* copy data */ { source = source0 + TBL_offset(tp,1,j); dest = tn->addres + TBL_offset(tn,1,j); len = (irow -1) * (j ? tp->bytes[j-1] : sizeof(int)); oscopy(dest,source,len); dest +=len; source += (irow +nr-1) * (j ? tp->bytes[j-1] : sizeof(int)); len = (tp->rows - irow -nr +1) * (j ? tp->bytes[j-1] : sizeof(int)); oscopy(dest,source,len); } if (status = MID_RETNAM(tp->imno, table_name, sizeof(table_name))) return(TBL_errf(status, "(in row expansion)")); if (status = TCTCLO(tid)) return(status); if (status = TCTCLO(new_tid)) return(status); if (status = SCFDEL(table_name)) return(TBL_errf(status, "(in row expansion)")); if (status = SCFRNM(TBL_tmpname, table_name)) return(TBL_errf(status, "(in row expansion)")); new_tid = tid; /* Tell that we want to keep the Old Number */ status = TCTOPN(table_name, F_IO_MODE, &new_tid); if ((status == ERR_NORMAL) && (new_tid != tid)) SCTPUT("++++ Table Number Changed!"); return (status); }