This commit is contained in:
Oliver Lehmann 1989-04-24 19:14:28 +00:00
parent 9754760a94
commit c2f0294c39
1 changed files with 733 additions and 0 deletions

View File

@ -0,0 +1,733 @@
# include <stdio.h>
# include "gen.h"
# include "../h/dbs.h"
# include "../h/aux.h"
# include "../h/symbol.h"
# include "../h/access.h"
# define N MERGESIZE
# ifdef MEM_E
# define MEM COREBUFSIZE
char start[MEM] = {0};
# else
# define MEM ((char *) COREBUFSIZE)
# endif
# define BUCKETSIZE sizeof (long)
# define ENDKEY (MAXDOM + 1)
char SYSSORT[] = "_SYS";
static char File[15];
static char DBU_buf[TUP_BUF_SIZ];
static char *DBU_ptr;
static char Descsort[MAXDOM + 1];
static DESC Desc;
static char **Lspace;
static char *Tspace;
static char *Infile;
static char *Outfile;
char *Fileset;
static char *Filep;
char *AApath;
static long Ccount;
static long Page;
static long Tupsout;
static int Outpipe = -2; /* fd to write to modify */
static unsigned int Memory; /* available memory buffer size */
# ifdef VPGSIZE
int AApgsize = PGSIZE;
int AAmaxtup = MAXTUP;
int AAltsize = 0;
# endif
static short Trace;
static short Bucket;
static short Nfiles;
static short Nlines;
static short Reorg;
static short AppendOutput;
static struct tup_id Lowtid;
static struct tup_id Hightid;
extern int term();
extern int cmpa();
/*
** argv[0] -- sx_dbu for sorting or
** rx_dbu for reorganization
** and x is the fd for outfile or '_'
**
** argv[1] -- Fileset (process id)
**
** argv[2] -- trace information
** comes from trace flag Z23
**
** The bits used are:
** 0001 main trace info
** 0002 secondary trace info
** 0004 terciary trace info
** 0010 don't truncate temps
** 0020 don't unlink temps
** 0040 print am page refs
** 0100 print am tuple gets
**
** argv[3] -- pathname of DBS subtree
**
** argv[4] -- page size of data base
**
** argv[5] -- name of descritor file
**
** argv[6] -- name of infile
**
** argv[7] -- name of outfile
*/
main(argc, argv)
int argc;
char **argv;
{
register int i;
register int j;
register int maxkey;
short rev;
# ifndef MEM_E
register char *start;
register char *stopp;
extern char *sbrk();
extern char *brk();
# endif
extern char *setfil();
extern char *AAproc_name;
extern int (*AAexitfn)();
AAproc_name = "DB_SORT";
AAexitfn = term;
Reorg = **argv == 'r';
if ((i = (*argv)[1]) != '_')
{
Outpipe = i - '0';
Outpipe = 10 * Outpipe + (*argv)[2] - '0';
}
Fileset = *++argv;
AA_atoi(*++argv, &Trace);
AApath = *++argv;
# ifdef VPGSIZE
AA_atoi(*++argv, &rev);
AApgsize = rev;
/* get the linetab size, the difference */
AAltsize = (PGSIZE - AApgsize) / sizeof (short);
# else
argv++;
# endif
if (Trace & 01)
printf("DB_SORT: %s path %s set %s pipe %d\n",
Reorg? "Reorg": "Sort", AApath, Fileset, Outpipe);
if ((i = open(*++argv, 0)) < 0)
AAsyserr(11055, *argv);
if (read(i, &Desc, sizeof Desc) < sizeof Desc)
AAsyserr(11049);
close(i);
/* set up Descsort to indicate the sort order for tuple */
/* if domain zero is given prepare to generate "hash bucket"
** value for tuple */
maxkey = 0;
for (i = 0; i <= Desc.reldum.relatts; i++)
if (j = Desc.relgiven[i])
{
if ((rev = j) < 0)
j = -j;
if (maxkey < j)
maxkey = j;
Descsort[--j] = rev < 0? -i: i;
}
Descsort[maxkey] = ENDKEY; /* mark end of list */
Tup_size = Desc.reldum.relwid;
if (Bucket = !Descsort[0])
{
/* we will be generating hash bucket */
Tup_size += BUCKETSIZE;
Desc.relfrml[0] = BUCKETSIZE;
Desc.relfrmt[0] = INT;
Desc.reloff[0] = Desc.reldum.relwid;
}
if (Trace & 01)
{
printf("Bucket is %d,Sort is:\n", Bucket);
for (i = 0; ctou(j = Descsort[i]) != ENDKEY; i++)
printf("Descsort[%d]=%d\n", i, j);
}
if (i = (maxkey - Bucket - Desc.reldum.relatts))
AAsyserr(11050, -i);
Infile = *++argv;
Outfile = (Outpipe > 0)? "PIPE": *++argv;
# ifdef MEM_E
Memory = MEM;
# else
/* get up to MEM-K bytes of memory for buffers. Note that mem */
/* must end up positive so that Nlines computation is right */
start = sbrk((char *) 0);
stopp = MEM;
while (brk(stopp) == (char *) -1)
stopp -= 512;
Memory = stopp - start;
# endif
Lspace = (char **) start;
/* compute pointers and sizes into buffer memory */
Nlines = Memory / (Tup_size + sizeof (char *));
Tspace = (char *) (Lspace + Nlines);
if (Trace & 01)
printf("Tspace=0%o,Lspace=0%o,Nlines=%u,mem=0%o,start=0%o\n",
Tspace, Lspace, Nlines, Memory, start);
/* set up temp files */
AAconcat(AAztack(SYSSORT, Fileset), "Sxxxx", File);
for (Filep = File; *Filep != 'x'; Filep++)
continue;
/* initialize tids for full scan */
Page = 0L;
Lowtid.line_id = SCANTID;
AAstuff_page(&Lowtid, &Page);
Page = -1L;
Hightid.line_id = SCANTID;
AAstuff_page(&Hightid, &Page);
Page = 1L;
/* open relation */
close(0);
if ((Desc.relfp = open(Infile, 0)) < 0)
AAsyserr(11055, Infile);
Desc.relopn = RELROPEN(Desc.relfp);
signal(2, term);
signal(3, term);
while (Desc.relopn)
{
/* sort stage -- create a bunch of temporaries */
Ccount = 0;
Tupsout = 0;
Nfiles = 1;
if (Trace & 01)
printf("sorting\n");
sort();
if (Trace & 01)
{
printf("done sorting\n%ld tuples written to %d files\n", Tupsout, Nfiles - 1);
printf("sort required %ld compares\n", Ccount);
}
/* merge stage -- merge up to N temps into a new temp */
Ccount = 0;
for (i = 1; i + N < Nfiles; i += N)
{
makfile(setfil(Nfiles++));
merge(i, i + N);
}
/* merge last set of temps into target file */
if (i != Nfiles)
{
oldfile();
merge(i, Nfiles);
}
if (Trace & 01)
{
printf("%ld tuples in out file\n", Tupsout);
printf("merge required %ld compares\n", Ccount);
}
}
term(0);
}
sort()
{
register char *cp;
register char **lp;
register int i;
register int done;
char *xp;
long ntups;
long pageid;
extern char *setfil();
extern long AArhash();
extern char *AAbmove();
done = 0;
ntups = 0;
do
{
cp = Tspace;
lp = Lspace;
while (lp < Lspace + Nlines)
{
if (i = AAam_get(&Desc, &Lowtid, &Hightid, cp, TRUE))
{
if (i < 0)
AAsyserr(11051, i);
close(Desc.relfp);
Desc.relopn = 0;
goto step_ok;
}
if (Reorg && Page != AAcc_head->mainpg)
{
Page = AAcc_head->mainpg;
Lowtid.line_id = SCANTID;
step_ok:
done++;
break;
}
if (Bucket)
{
/* compute hash bucket and insert at end */
pageid = AArhash(&Desc, cp);
AAbmove(&pageid, cp + Desc.reldum.relwid, BUCKETSIZE);
}
*lp++ = cp;
cp += Tup_size;
ntups++;
}
qsort(Lspace, lp - Lspace, sizeof (char *), cmpa);
if (!done || Nfiles != 1)
makfile(setfil(Nfiles++));
else
oldfile();
while (lp > Lspace)
{
cp = *--lp;
xp = cp;
if ((lp == Lspace) || cmpa(&xp, &lp[-1]))
{
tup_write(cp);
Tupsout++;
}
}
if (Tup_fd != Outpipe)
tup_close();
} while (!done);
if (Trace & 01)
printf("%ld tuples in\n", ntups);
}
merge(low, high)
int low;
int high;
{
register struct tup_hdr *merg;
register int i;
register int j;
register char *f;
register unsigned int blen;
register unsigned int mlen;
register char *mem;
char *yesno;
struct tup_hdr *merg_buf[N + 1];
extern char *setfil();
if (Trace & 02)
printf("merge %d to %d\n", low, high);
/* compute length of merge buffers */
j = sizeof (struct tup_hdr);
i = ((Memory / (high - low)) - j) / PGSIZE;
if ((blen = i * PGSIZE) > 32768L - PGSIZE)
blen = 32768L - PGSIZE;
mlen = ALIGNMENT(j + blen);
blen += PGSIZE;
if (Trace & 02)
printf("merge mem 0%o buflen 0%o\n", Memory, blen);
mem = (char *) Lspace;
for (j = 0, i = low; i < high; i++)
{
merg_buf[j] = merg = (struct tup_hdr *) mem;
if ((merg->tup_fd = open(f = setfil(i), 0)) < 0)
AAsyserr(11055, f);
merg->tup_ptr = merg->tup_buf;
merg->tup_end = merg->tup_buf;
merg->tup_len = blen;
merg->tup_no = i;
if (!next_tuple(merg))
j++;
mem += mlen;
}
i = j - 1;
if (Trace & 04)
printf("start merg with %d\n", i);
while (i >= 0)
{
if (Trace & 04)
printf("mintup %d\n", i);
if (mintup(merg_buf, i, cmpa))
{
tup_write(merg_buf[i]->tup_ptr);
Tupsout++;
}
if (next_tuple(merg = merg_buf[i]))
{
yesno = "not ";
if (!(Trace & 010))
{
/* truncate temporary files to zero length */
yesno = "";
close(creat(setfil(merg->tup_no), FILEMODE));
}
if (Trace & 02 || Trace & 010)
printf("dropping and %struncating %s\n", yesno, setfil(merg->tup_no));
i--;
}
}
if (Tup_fd != Outpipe)
tup_close();
}
/*
** Mintup puts the smallest tuple in merg_buf[cnt-1].
** If the tuple is a duplicate of another then
** mintup returns 0, else 1.
**
** Cnt is the number of compares to make; i.e.
** merg_buf[cnt] is the last element.
*/
mintup(merg_buf, cnt, cmpfunc)
struct tup_hdr *merg_buf[];
int cnt;
int (*cmpfunc)();
{
register struct tup_hdr **next;
register struct tup_hdr **last;
register int nodup;
register struct tup_hdr *temp;
register int j;
nodup = TRUE;
next = merg_buf;
last = &next[cnt];
while (cnt--)
{
if (j = (*cmpfunc)(*last, *next))
{
/* tuples not equal. keep smallest */
if (j < 0)
{
/* exchange */
temp = *last;
*last = *next;
*next = temp;
nodup = TRUE;
}
}
else
nodup = FALSE;
next++;
}
return (nodup);
}
next_tuple(merg)
register struct tup_hdr *merg;
{
register int eof;
extern char *tup_read();
if (eof = !tup_read(merg))
close(merg->tup_fd);
return (eof);
}
/*
** Convert the number i to a char
** sequence 1, 2, ..., 10, 11, etc.
*/
char *setfil(i)
register int i;
{
AA_itoa(--i, Filep);
return (File);
}
oldfile()
{
register int i;
register char *name;
register int fd;
long off;
extern long lseek();
extern char *AAbmove();
name = Outfile;
if (Trace & 02)
printf("OLDFILE: %s\n", name);
if (Outpipe > 0)
{
if (AppendOutput)
{
if (Tup_fd == Outpipe)
return;
if (i = DBU_ptr - DBU_buf)
Tup_ptr = AAbmove(DBU_buf, Tup_buf, i);
else
Tup_ptr = Tup_buf;
}
else
Tup_ptr = Tup_buf;
Tup_fd = Outpipe;
}
else if (AppendOutput)
{
if ((fd = open(name, 2)) < 0)
AAsyserr(11055, name);
if ((off = lseek(fd, 0L, 2)) < 0)
AAsyserr(11055, name);
if (i = off % PGSIZE)
{
if (lseek(fd, off - i, 0) < 0 || read(fd, Tup_buf, i) != i)
AAsyserr(11055, name);
lseek(fd, off - i, 0);
}
Tup_ptr = &Tup_buf[i];
Tup_fd = fd;
}
else
makfile(name);
AppendOutput++;
}
makfile(name)
register char *name;
{
register int i;
extern char *AAbmove();
if (Trace & 02)
printf("MAKFILE: %s\n", name);
if (Outpipe > 0 && AppendOutput)
{
if (i = Tup_ptr - Tup_buf)
DBU_ptr = AAbmove(Tup_buf, DBU_buf, i);
else
DBU_ptr = DBU_buf;
}
if ((Tup_fd = creat(name, FILEMODE)) < 0)
AAsyserr(11055, name);
Tup_ptr = Tup_buf;
}
term(error)
register int error;
{
register int i;
extern char *setfil();
if (Nfiles == 1)
Nfiles++;
if (Trace & 020)
printf("temp files not removed\n");
else
for (i = 1; i < Nfiles; i++)
unlink(setfil(i));
if (Tup_fd >= 0)
tup_close();
if (Outpipe > 0)
close(Outpipe);
fflush(stdout);
sync();
exit(error);
}
AAunlall()
{
}
cmpa(a, b)
char **a;
char **b;
{
register char *tupa;
register char *tupb;
register int frml;
register int i;
register int dom;
register int off;
char *dp;
int frmt;
char *pa;
char *pb;
char af[sizeof (double)];
char bf[sizeof (double)];
pa = *a;
pb = *b;
Ccount++;
dp = Descsort;
while (ctou(i = *dp++) != ENDKEY)
{
if ((dom = i) < 0)
dom = -i;
frml = ctou(Desc.relfrml[dom]);
frmt = Desc.relfrmt[dom];
off = Desc.reloff[dom];
tupa = &pa[off];
tupb = &pb[off];
if (i < 0)
{
tupb = tupa;
tupa = &pb[off];
}
if (frmt == CHAR)
{
if (i = AAscompare(tupb, frml, tupa, frml))
return (i);
continue;
}
/* domain is a numeric type */
if (AAbequal(tupa, tupb, frml))
continue;
/* copy to even word boundary */
AAbmove(tupa, af, frml);
AAbmove(tupb, bf, frml);
tupa = af;
tupb = bf;
switch (frmt)
{
case INT:
switch (frml)
{
case sizeof (char):
return (ctoi(((I1TYPE *) tupa)->i1type) > ctoi(((I1TYPE *) tupb)->i1type)? -1: 1);
case sizeof (short):
return (((I2TYPE *) tupa)->i2type > ((I2TYPE *) tupb)->i2type? -1: 1);
case sizeof (long):
return (((I4TYPE *) tupa)->i4type > ((I4TYPE *) tupb)->i4type? -1: 1);
}
case FLOAT:
# ifndef NO_F4
switch (frml)
{
case sizeof (float):
return (((F4TYPE *) tupa)->f4type > ((F4TYPE *) tupb)->f4type? -1: 1);
case sizeof (double):
# endif
return (((F8TYPE *) tupa)->f8type > ((F8TYPE *) tupb)->f8type? -1: 1);
# ifndef NO_F4
}
# endif
}
}
return (0);
}
/*
** Replacement for access method routine AAgetpage();
** and associated globals and routines.
*/
ACCBUF *AAcc_head;
static ACCBUF AAcc_buf;
static long AAccuread;
static long AAccuwrite;
AAgetpage(d, tid)
register DESC *d;
struct tup_id *tid;
{
register int i;
register ACCBUF *b;
long pageid;
extern long lseek();
if (Trace & 0100)
{
printf("GET_PAGE: %.14s,", d->reldum.relid);
AAdumptid(tid);
}
if (!(b = AAcc_head))
{
/* initialize buffer */
AAcc_head = &AAcc_buf;
b = &AAcc_buf;
b->thispage = -1L;
}
AApluck_page(tid, &pageid);
i = 0;
if (b->thispage != pageid)
{
if (Trace & 040)
printf("GET_PAGE: rdg pg %ld\n", pageid);
b->thispage = pageid;
if (lseek(d->relfp, pageid * AApgsize, 0) < 0L)
i = AMSEEK_ERR;
else if (read(d->relfp, b, AApgsize) != AApgsize)
i = AMREAD_ERR;
AAccuread++;
}
return (i);
}
AAresetacc()
{
return (0);
}
AAam_error(err)
register int err;
{
return (err);
}