Annotation of 42BSD/ingres/source/dbu/omodify.c, revision 1.1.1.1

1.1       root        1: # include      <stdio.h>
                      2: # include      <ingres.h>
                      3: # include      <pv.h>
                      4: # include      <aux.h>
                      5: # include      <access.h>
                      6: # include      <batch.h>
                      7: # include      <lock.h>
                      8: # include      <opsys.h>
                      9: # include      <func.h>
                     10: # include      <version.h>
                     11: # include      <sccs.h>
                     12: 
                     13: SCCSID(@(#)modify.c    7.1     2/5/81)
                     14: 
                     15: extern short   tTdbu[];
                     16: extern int     modify();
                     17: extern         int     null_fn();
                     18: 
                     19: struct fn_def ModifyFn =
                     20: {
                     21:        "MODIFY",
                     22:        modify,
                     23:        null_fn,
                     24:        null_fn,
                     25:        NULL,
                     26:        0,
                     27:        tTdbu,
                     28:        100,
                     29:        'Z',
                     30:        0
                     31: };
                     32: 
                     33: /*
                     34: **  MODIFY -- converts any relation to the specified
                     35: **             storage structure
                     36: **
                     37: **     arguments:
                     38: **     0 - relation name
                     39: **     1 - storage structure ("heap", "cheap", "hash", "chash",
                     40: **             "isam", "cisam")
                     41: **     2 - "name" for attribute names, or "num" for numbers
                     42: **     3 - key1
                     43: **     4 - key2
                     44: **         .
                     45: **         .
                     46: **     i - null
                     47: **     i+1 - option name (e.g., "fillfactor")
                     48: **     i+2 - option value
                     49: **         .
                     50: **         .
                     51: **
                     52: **     If all the options default, parameter i -> pc are omitted.
                     53: **     If no keys are provided, parameter 2 is omitted.
                     54: */
                     55: 
                     56: int            F_fac, Mn_pages, Mx_pages;
                     57: 
                     58: struct modtab
                     59: {
                     60:        char    *type;
                     61:        char    newrelspec;
                     62:        char    yeskeys;
                     63:        char    sortit;
                     64:        char    yes_seq;
                     65:        int     f_fac;
                     66:        int     mn_pages;
                     67:        int     mx_pages;
                     68: };
                     69: 
                     70: 
                     71: struct modtab  Modtab[] =
                     72: {
                     73:        /* type         spec    keys    sort    seq     ffac    min     max */
                     74: 
                     75:        "heap",         M_HEAP, FALSE,  FALSE,  FALSE,  0,      0,      0,
                     76:        "cheap",        -M_HEAP,FALSE,  FALSE,  FALSE,  0,      0,      0,
                     77:        "hash",         M_HASH, TRUE,   TRUE,   FALSE,  50,     10,     -1,
                     78:        "chash",        -M_HASH,TRUE,   TRUE,   FALSE,  75,     1,      -1,
                     79:        "isam",         M_ISAM, TRUE,   TRUE,   FALSE,  80,     0,      0,
                     80:        "cisam",        -M_ISAM,TRUE,   TRUE,   FALSE,  100,    0,      0,
                     81:        "heapsort",     M_HEAP, TRUE,   TRUE,   TRUE,   0,      0,      0,
                     82:        "cheapsort",    -M_HEAP,TRUE,   TRUE,   TRUE,   0,      0,      0,
                     83:        "truncated",    M_TRUNC,FALSE,  FALSE,  FALSE,  0,      0,      0,
                     84:        0
                     85: };
                     86: 
                     87: struct mod_info
                     88: {
                     89:        char    outfile[MAXNAME + 4];   /* result file filled by ksort */
                     90:        char    formfile[MAXNAME + 4];  /* file with descriptor for ksort */
                     91:        char    infile[MAXNAME + 4];    /* input file for ksort (relation itself */
                     92:        char    reltemp[MAXNAME + 4];   /* file holding new relation */
                     93:        char    spfile[MAXNAME + 4], spflag;    /* isam spool file for overflow */
                     94: };
                     95: 
                     96: struct mod_info        Mod_info;
                     97: 
                     98: 
                     99: 
                    100: 
                    101: 
                    102: modify(pc, pv)
                    103: int    pc;
                    104: PARM   *pv;
                    105: {
                    106:        register int            i;
                    107:        register char           *rname;
                    108:        register struct modtab  *mp;
                    109:        int                     sorted;
                    110:        DESC                    dold, dnew;
                    111:        long                    temptid;
                    112:        extern int              Noupdt;
                    113: 
                    114:        
                    115: #      ifdef xZTR1
                    116:        if (tTf(34, -1))
                    117:        {
                    118:                printf("enter modify\n");
                    119:                prvect(pc, pv);
                    120:        }
                    121: #      endif
                    122: 
                    123:        pv[pc].pv_val.pv_str = NULL;
                    124: 
                    125:        /* check for nice parameters */
                    126:        if (pc < 2)
                    127:                syserr("MODIFY: pc %d", pc);
                    128: 
                    129:        /* save relation name for error messages */
                    130:        rname = (pv++)->pv_val.pv_str;  /* *pv now pointes to storage spec */
                    131: 
                    132:        /* check for good relation */
                    133:        i = openr(&dold, 0, rname);
                    134:        if (i == AMOPNVIEW_ERR)
                    135:                return (error(5519, rname, 0));
                    136:        if (i > 0)
                    137:                /* reln does not exist */
                    138:                return (error(5500, rname, 0)); 
                    139:        else if (i < 0)
                    140:                syserr("MODIFY: openr (%.14s) %d", rname, i);
                    141:        /* can only modify a relation you own and isn't a sys rel */
                    142:        
                    143:        if (!bequal(Usercode, dold.reldum.relowner, 2))
                    144:        {
                    145:                i = 5501;
                    146:        }
                    147:        if ((dold.reldum.relstat & S_CATALOG) && Noupdt)
                    148:        {
                    149:                i = 5504;
                    150:        }
                    151:        if (i)
                    152:        {
                    153:                closer(&dold);
                    154:                return (error(i, rname, 0));
                    155:        }
                    156: 
                    157:        /*
                    158:        ** Form descriptor for new relation. Here we need to
                    159:        ** separate the pages from the old and new relations.
                    160:        ** Since pages are identified by the TID of the relation
                    161:        ** relation tuple, both old and new have the same identifiers.
                    162:        ** To avoid this problem, a special TID is hand crafted for
                    163:        ** the new relation.
                    164:        */
                    165:        bmove(&dold, &dnew, sizeof dnew);
                    166:        dnew.reltid.s_tupid.line_id = (char) -2;        /* choose impossible reltid */
                    167: 
                    168:        /* In case of an interrupt from a previous modify,
                    169:        ** there might be pages around. Get rid of them.
                    170:        */
                    171:        cleanrel(&dnew);
                    172: 
                    173:        ingresname(dold.reldum.relid, dold.reldum.relowner, Mod_info.infile);
                    174: 
                    175:        /* scan for entry in relspec table */
                    176:        for (mp = Modtab; mp->type; mp++)
                    177:                if (sequal(mp->type, pv->pv_val.pv_str))
                    178:                        break;
                    179: 
                    180:        /* if not found, error */
                    181:        if (!mp->type)
                    182:        {
                    183:                closer(&dold);
                    184:                return (error(5510, rname, pv->pv_val.pv_str, 0));      /* bad relspec */
                    185:        }
                    186:        dnew.reldum.relspec = mp->newrelspec;
                    187:        if (dnew.reldum.relspec == M_TRUNC)
                    188:                dnew.reldum.relspec = M_HEAP;
                    189: 
                    190:        pv++;   /* now points to first parameter */
                    191: 
                    192:        F_fac = mp->f_fac;
                    193:        Mn_pages = mp->mn_pages;
                    194:        Mx_pages = mp->mx_pages;
                    195: 
                    196:        /* get the key domains information */
                    197:        if (i = getkeys(&pv, rname, &dnew, mp))
                    198:        {
                    199:                closer(&dold);
                    200:                return (i);     /* user error */
                    201:        }
                    202: 
                    203:        /* get fillfactor and other options if any */
                    204:        if (i = getfill(pv, rname, mp))
                    205:        {
                    206:                closer(&dold);
                    207:                return (i);     /* user error */
                    208:        }
                    209: 
                    210: 
                    211:        /* lock the relation relation */
                    212:        if (Lockrel)
                    213:        {
                    214:                get_p_tid(&dold, &temptid);
                    215:                setrll(A_SLP, temptid, M_EXCL);
                    216:        }
                    217: 
                    218:        /* compute new relation parameters & build descriptor */
                    219:        make_newrel(&dnew);
                    220: 
                    221:        if (sorted = (mp->sortit && (dold.reldum.reltups != 0)))
                    222:                sortrel(&dold, &dnew);
                    223: 
                    224:        /* physically create the new relation */
                    225:        if (formatpg(&dnew, dnew.reldum.relprim) != 0)
                    226:                syserr("modify: formatpg");
                    227: 
                    228:        /* clear relgiven field; if heap remove any keys */
                    229:        clearkeys(&dnew);
                    230:        if (abs(dnew.reldum.relspec) == M_HEAP)
                    231:                for (i = 1; i <= dnew.reldum.relatts; i++)
                    232:                        dnew.relxtra[i] = 0;
                    233: 
                    234:        if (mp->newrelspec != M_TRUNC)
                    235:                fill_rel(&dold, &dnew, sorted);
                    236: 
                    237:        closer(&dold);  /* error return is impossible */
                    238:        if (abs(dnew.reldum.relspec) == M_ISAM)
                    239:        {
                    240:                if (i = bldindex(&dnew))
                    241:                        syserr("bldindex: %.14s %d", dnew.reldum.relid, i);
                    242:                unspool(&dnew);
                    243:        }
                    244: 
                    245:        /*
                    246:        ** New relation is now complete. The system relations need to
                    247:        ** be updated. First destroy all buffers with pages from the
                    248:        ** new relation.
                    249:        */
                    250:        if (i = cleanrel(&dnew))
                    251:                syserr("modify:clean new %d,%.14s", i, dnew.reldum.relid);
                    252: 
                    253:        fill_batch(&dold, &dnew);
                    254: 
                    255:        /*
                    256:        ** Close the file for the new relation. This must be
                    257:        ** done after the fill_batch in case we are modifing
                    258:        ** the attribute relation.
                    259:        */
                    260:        close(dnew.relfp);
                    261:        dnew.relopn = 0;
                    262:        ruboff("modify");
                    263:        modupdate();
                    264:        rubon();
                    265: 
                    266:        if (Lockrel)
                    267:                unlrl(temptid);
                    268: 
                    269: #      ifdef xZTM
                    270:        if (tTf(35, 1))
                    271:                timtrace(16, 0);
                    272: #      endif
                    273:        return (0);
                    274: }
                    275: 
                    276: 
                    277: getkeys(ppv, relname, d, mp)
                    278: PARM           **ppv;
                    279: char           *relname;
                    280: register DESC  *d;
                    281: struct modtab  *mp;
                    282: {
                    283:        register PARM           *pv;
                    284:        register char           *cp;
                    285:        int                     namemode, sort_only, as_ds;
                    286:        int                     i, keyno, keywid;
                    287:        struct attribute        attkey, atttup;
                    288:        TID                     tid;
                    289:        extern DESC             Attdes;
                    290: 
                    291:        pv = *ppv;      /* copy list of params */
                    292: 
                    293:        /* zero key info */
                    294:        for (i = 0; i <= d->reldum.relatts; i++)
                    295:                d->relxtra[i] = d->relgiven[i] = 0;
                    296: 
                    297:        /* determine whether there are any keys at all */
                    298:        keyno = 0;
                    299:        keywid = 0;
                    300:        sort_only = FALSE;
                    301:        cp = pv->pv_val.pv_str;
                    302: 
                    303:        if (cp == NULL || *cp == NULL)
                    304:        {
                    305:                /* no key information. default as needed */
                    306:                if (mp->yeskeys)
                    307:                {
                    308:                        cp = "\1";      /* default to first key */
                    309:                        namemode = FALSE;
                    310:                }
                    311:                else
                    312:                        pv++;   /* point one to far */
                    313:        }
                    314:        else
                    315:        {
                    316:                /* check for name mode */
                    317:                if (namemode = sequal(cp, "name"))
                    318:                {
                    319: 
                    320:                        /* check attribute names, and convert them to numbers */
                    321:                        opencatalog("attribute", 0);
                    322:                        setkey(&Attdes, &attkey, Mod_info.infile, ATTRELID);
                    323:                        setkey(&Attdes, &attkey, Usercode, ATTOWNER);
                    324:                }
                    325:                pv++;   /* inc to next key */
                    326:                cp = (pv++)->pv_val.pv_str;
                    327:        }
                    328: 
                    329: 
                    330:        /* scan for attribute names */
                    331:        for (; cp != NULL; cp = (pv++)->pv_val.pv_str)
                    332:        {
                    333:                /* check for separator between keys & options */
                    334:                if (*cp == NULL)
                    335:                {
                    336:                        pv++;   /* point two past NULL */
                    337:                        break;
                    338:                }
                    339: 
                    340:                if (namemode)
                    341:                {
                    342:                        /* check for "sort only" attribute */
                    343:                        if (*cp == '#')
                    344:                        {
                    345:                                cp++;   /* inc to start of name */
                    346:                                sort_only = TRUE;
                    347:                        }
                    348: 
                    349:                        /* check for ascending/descending modifier */
                    350:                        if ((as_ds = modseqkey(cp, relname, mp->yes_seq)) > 0)
                    351:                                return (as_ds); /* error */
                    352: 
                    353:                        setkey(&Attdes, &attkey, cp, ATTNAME);
                    354:                        i = getequal(&Attdes, &attkey, &atttup, &tid);
                    355:                        if (i < 0)
                    356:                                syserr("MODIFY: geteq(att) %d", i);
                    357:                        if (i > 0)
                    358:                        {
                    359:                                return (error(5511, relname, cp, 0));   /* bad att name */
                    360:                        }
                    361:                        i = atttup.attid;
                    362:                }
                    363:                else
                    364:                {
                    365:                        i = *cp;
                    366:                        as_ds = 0;
                    367:                }
                    368: 
                    369:                /* add new key to descriptor */
                    370:                keyno++;
                    371:                if (!sort_only)
                    372:                {
                    373:                        d->relxtra[i] = keyno;
                    374:                        keywid += (d->relfrml[i] & I1MASK);
                    375:                }
                    376:                if (d->relgiven[i])
                    377:                        return (error(5507, relname, cp, 0));   /* duplicate attribute */
                    378:                d->relgiven[i] = as_ds == 0 ? keyno : -keyno;
                    379:        }
                    380:        pv--;   /* back up one to point to "-1" terminator */
                    381: 
                    382: 
                    383:        if (abs(d->reldum.relspec) == M_ISAM && keywid > (MAXTUP / 2 - 4))
                    384:        {
                    385:                return (error(5508, relname, iocv(keywid), 0));
                    386:        }
                    387: 
                    388:        /* if a heap, there can be no keys */
                    389:        if (!mp->yeskeys && keyno != 0)
                    390:        {
                    391:                return (error(5502, relname, mp->type, 0));     /* no keys allowed on heap */
                    392:        }
                    393: 
                    394:        /* fill out default sort on remainder of keys */
                    395:        if (mp->yeskeys)
                    396:                for (i = 1; i <= d->reldum.relatts; i++)
                    397:                        if (d->relgiven[i] == 0)
                    398:                                d->relgiven[i] = ++keyno;
                    399:        *ppv = pv;
                    400:        return (0);
                    401: }
                    402: 
                    403: 
                    404: modseqkey(domain, relname, seq_ok)
                    405: char   *domain;
                    406: char   *relname;
                    407: int    seq_ok;
                    408: {
                    409:        register char   *cp, c;
                    410:        register int    ret;
                    411: 
                    412:        ret = 0;
                    413: 
                    414:        for (cp = domain; c = *cp++; )
                    415:                if (c == ':')
                    416:                        break;
                    417: 
                    418:        if (c != '\0')
                    419:        {
                    420:                /* replace ":" with null */
                    421:                *(cp - 1) = '\0';
                    422: 
                    423:                /* verify sequence is valid */
                    424:                if (!seq_ok)
                    425:                        ret = error(5520, relname, cp, domain, 0);
                    426:                else if (sequal("descending", cp) || sequal("d", cp))
                    427:                        ret = -1;
                    428:                else if (!(sequal("ascending", cp) || sequal("a", cp)))
                    429:                        ret = error(5518, relname, cp, domain, 0);
                    430:        }
                    431: 
                    432:        return (ret);
                    433: }
                    434: /*
                    435: **     GETFILL -- Get fill factor and minimum pages parameters
                    436: **             from argument list, convert them from ascii to integer
                    437: **             and store them in global variables.  If the global
                    438: **             variable for the corresponding parameter is zero,
                    439: **             it means that that parameter is not allowed and an
                    440: **             error is generated.
                    441: */
                    442: 
                    443: /*ARGSUSED*/
                    444: getfill(pv, rel, mp)
                    445: register PARM  *pv;
                    446: char           *rel;
                    447: struct modtab  *mp;
                    448: {
                    449:        register char   *p1;
                    450:        register int    err;
                    451:        char            *p2;
                    452:        int             fill_flag, min_flag, max_flag;
                    453: 
                    454:        err = 0;
                    455:        fill_flag = min_flag = max_flag = FALSE;
                    456: 
                    457:        while ((p1 = (pv++)->pv_val.pv_str) != NULL)
                    458:        {
                    459:                p2 = (pv++)->pv_val.pv_str;
                    460:                if (sequal(p1, "fillfactor"))
                    461:                {
                    462:                        if (F_fac == 0 || fill_flag)
                    463:                        {
                    464:                                err = 5512;
                    465:                                break;
                    466:                        }
                    467:                        p1 = p2;
                    468:                        atoi(p1, &F_fac);
                    469:                        if (F_fac > 100 || F_fac < 1)
                    470:                        {
                    471:                                err = 5513;
                    472:                                break;
                    473:                        }
                    474:                        fill_flag = TRUE;
                    475:                        continue;
                    476:                }
                    477:                if (sequal(p1, "minpages"))
                    478:                {
                    479:                        if (Mn_pages == 0 || min_flag)
                    480:                        {
                    481:                                err = 5512;
                    482:                                break;
                    483:                        }
                    484:                        p1 = p2;
                    485:                        atoi(p1, &Mn_pages);
                    486:                        if (Mn_pages < 1)
                    487:                        {
                    488:                                err = 5514;
                    489:                                break;
                    490:                        }
                    491:                        if (max_flag && (Mn_pages > Mx_pages))
                    492:                        {
                    493:                                err = 5517;
                    494:                                break;
                    495:                        }
                    496:                        min_flag = TRUE;
                    497:                        continue;
                    498:                }
                    499:                if (sequal(p1, "maxpages"))
                    500:                {
                    501:                        if (Mx_pages == 0 || max_flag)
                    502:                        {
                    503:                                err = 5512;
                    504:                                break;
                    505:                        }
                    506:                        p1 = p2;
                    507:                        atoi(p1, &Mx_pages);
                    508:                        if (Mx_pages < 1)
                    509:                        {
                    510:                                err = 5516;
                    511:                                break;
                    512:                        }
                    513:                        if (min_flag && (Mn_pages > Mx_pages))
                    514:                        {
                    515:                                err = 5517;
                    516:                                break;
                    517:                        }
                    518:                        max_flag = TRUE;
                    519:                        continue;
                    520:                }
                    521:                err = 5515;
                    522:                break;
                    523:        }
                    524:        if (err)
                    525:                return (error(err, rel, p1, 0));
                    526:        return (0);
                    527: }
                    528: /*
                    529: **  MAKE_NEWREL -- Create a file for the modified relation
                    530: **     and build one or more primary pages for the
                    531: **     relation based on its storage structure and the
                    532: **     number of tuples it must hold.
                    533: */
                    534: 
                    535: make_newrel(desc)
                    536: register DESC  *desc;
                    537: {
                    538:        register int    tups_p_page;
                    539: 
                    540:        concat(MODTEMP, Fileset, Mod_info.reltemp);
                    541:        close(creat(Mod_info.reltemp, FILEMODE));
                    542:        if ((desc->relfp = open(Mod_info.reltemp, 2)) < 0)
                    543:                syserr("MAKE_NEWREL: open %.14s %d", Mod_info.reltemp, desc->relfp);
                    544:        desc->relopn = (desc->relfp + 1) * -5;
                    545:        desc->reldum.relprim = 1;
                    546:        if (abs(desc->reldum.relspec) == M_HASH && F_fac > 0 && Mn_pages > 0)
                    547:        {
                    548:                /*
                    549:                ** Determine the number of primary pages. The following
                    550:                ** first determines the number of tuples/page which the
                    551:                ** relation should have in order to get the requested
                    552:                ** fillfactor. Then that number is divided into the
                    553:                ** number of tuples to get the number of primary pages.
                    554:                ** To avoid round off, it must guaranteed that the
                    555:                ** number of tuples per page must be at least 1.
                    556:                **
                    557:                ** primary_pages = #tuples / (#tuples/page * fillfactor)
                    558:                */
                    559:                tups_p_page = (((MAXTUP+2) / (desc->reldum.relwid+2)) * F_fac) / 100;
                    560:                if (tups_p_page == 0)
                    561:                        tups_p_page = 1;
                    562:                 /* we add one to simulate a ceiling function */
                    563:                desc->reldum.relprim = desc->reldum.reltups / tups_p_page + 1;
                    564:                if (desc->reldum.relprim < Mn_pages)
                    565:                        desc->reldum.relprim = Mn_pages;
                    566:                if (Mx_pages > 0 && desc->reldum.relprim > Mx_pages)
                    567:                        desc->reldum.relprim = Mx_pages;
                    568: #              ifdef xZTR1
                    569:                if (tTf(36, 0))
                    570:                        printf("using %ld prim pages\n", desc->reldum.relprim);
                    571: #              endif
                    572:        }
                    573:        desc->reldum.reltups = 0;
                    574:        return (0);
                    575: }
                    576: /*
                    577: **     SORTREL - Call KSORT to sort the given relation.  SORTREL
                    578: **             sets up the descriptor struct specifying the sort
                    579: **             keys and tells KSORT whether or not the hash key should
                    580: **             be included as a sort key.
                    581: */
                    582: 
                    583: sortrel(odesc, desc)
                    584: DESC           *odesc;
                    585: register DESC  *desc;
                    586: {
                    587:        extern char     *Pathname;
                    588:        register int    fp, i;
                    589:        char            savespec;
                    590:        char            buf[50];
                    591: 
                    592:        concat(ISAM_SORTED, Fileset, Mod_info.outfile);
                    593:        if (close(creat(Mod_info.outfile, FILEMODE)))
                    594:                syserr("SORTREL: creat %.14s", Mod_info.outfile);
                    595:        concat(ISAM_DESC, Fileset, Mod_info.formfile);
                    596:        if ((fp = creat(Mod_info.formfile, FILEMODE)) < 0)
                    597:                syserr("SORTREL: creat %.14s %d", Mod_info.formfile, fp);
                    598:        if (abs(desc->reldum.relspec) == M_HASH)
                    599:        {
                    600:                /* sort on hash bucket first */
                    601:                desc->relgiven[0] = 1;
                    602:                for (i = 1; i <= desc->reldum.relatts; i++)
                    603:                        desc->relgiven[i]++;
                    604:        }
                    605:        savespec = desc->reldum.relspec;
                    606:        desc->reldum.relspec = odesc->reldum.relspec;
                    607: 
                    608: # ifdef xZTR2
                    609:        if (tTf(36, 4))
                    610:        {
                    611:                printf("sortrel: ");
                    612:                printdesc(desc);
                    613:        }
                    614: # endif
                    615: 
                    616:        if (write(fp, desc, sizeof *desc) != sizeof *desc)
                    617:                syserr("SORTREL: desc write err");
                    618:        close(fp);
                    619:        desc->reldum.relspec = savespec;
                    620: 
                    621:        i = fork();
                    622:        if (i == -1)
                    623:                syserr("SORTREL: fork");
                    624:        if (i == 0)
                    625:        {
                    626:                for (i = 3; i < NOFILE; i++)
                    627:                        close(i);
                    628: # ifdef KSORTPATH
                    629:                smove(KSORTPATH, buf);
                    630: # else
                    631:                concat(Pathname, ztack("/bin/ksort", VERSION), buf);
                    632: # endif KSORTPATH
                    633: # ifdef xZTR2
                    634:                if (tTf(36, 0))
                    635:                {
                    636:                        printf("Calling ksort, args:\n");
                    637:                        printf("\tbuf = `%s'\n", buf);
                    638:                        printf("\tFileset = `%s'\n", Fileset);
                    639:                        printf("\ttTf = `%s'\n", iocv(tTf(37, -1)));
                    640:                        printf("\tformfile = `%s'\n", Mod_info.formfile);
                    641:                        printf("\tinfile = `%s'\n", Mod_info.infile);
                    642:                        printf("\toutfile = `%s'\n", Mod_info.outfile);
                    643:                }
                    644: # endif xZTR2
                    645:                execl(buf, buf, Fileset, iocv(tTf(37, -1)),
                    646:                        Mod_info.formfile, Mod_info.infile,
                    647:                        Mod_info.outfile, 0);
                    648:                syserr("SORTREL: exec %s", buf);
                    649:        }
                    650: 
                    651: # ifdef        xZTR1
                    652:        tTfp(36, 9, "SORTREL: after execl; pid = %d\n", i);
                    653: # endif
                    654: 
                    655:        if (fp = fullwait(i, "modify")) /* wait for ksort to complete */
                    656:                syserr("modify:ksort failed %d", fp);
                    657: 
                    658: # ifdef        xZTR1
                    659:        tTfp(36, 10, "SORTREL: after fullwait\n");
                    660: # endif
                    661: 
                    662:        unlink(Mod_info.formfile);
                    663:        return (0);
                    664: }
                    665: /*
                    666: **     FILL_REL -- Fill the new relation with tuples from either
                    667: **             the old relation or the output file of KSORT.
                    668: */
                    669: 
                    670: fill_rel(sdesc, desc, sortit)
                    671: register DESC  *sdesc, *desc;
                    672: char                   sortit;
                    673: {
                    674:        register int    i;
                    675:        char            tup_buf[MAXTUP], last_tup[MAXTUP];
                    676:        char            junk[4], newreltype, anytups, chkdups;
                    677:        int             need, j;
                    678:        long            lnum;
                    679:        TID             tid, stid, stidlim;
                    680:        FILE            *fp, *spfp;
                    681: 
                    682:        newreltype = abs(desc->reldum.relspec);
                    683:        if (sortit)
                    684:        {
                    685:                if ((fp = fopen(Mod_info.outfile, "r")) == NULL)
                    686:                        syserr("FILL_REL: fopen %.14s", Mod_info.outfile);
                    687:        }
                    688:        else
                    689:        {
                    690:                cleanrel(sdesc);        /* make sure each page is read fresh */
                    691:                find(sdesc, NOKEY, &stid, &stidlim);
                    692:        }
                    693:        if (newreltype == M_ISAM)
                    694:        {
                    695:                lnum = 0;
                    696:                stuff_page(&tid, &lnum);
                    697:                tid.line_id = 0;
                    698:                get_page(desc, &tid);
                    699:                concat(ISAM_SPOOL, Fileset, Mod_info.spfile);
                    700:                /* assume that spool file is not needed */
                    701:                spfp = NULL;
                    702:                Mod_info.spflag = FALSE;
                    703:                if (F_fac == 0)
                    704:                        F_fac = 100;
                    705:                /* setup relgiven field for kcompare later on */
                    706:                for (i = 1; i <= desc->reldum.relatts; i++)
                    707:                        desc->relgiven[i] = desc->relxtra[i];
                    708:        }
                    709:        desc->reladds = 0;
                    710:        anytups = FALSE;
                    711:        chkdups = !sortit;
                    712: # ifdef xZTR2
                    713:        if (tTf(36, 3))
                    714:        {
                    715:                printf("  FILLREL: ");
                    716:                printdesc(desc);
                    717:        }
                    718: # endif
                    719:        for (;;)
                    720:        {
                    721:                if (sortit)
                    722:                {
                    723:                        i = fread(tup_buf, 1, desc->reldum.relwid, fp);
                    724:                        if (i == 0)
                    725:                                break;
                    726:                        if (i != desc->reldum.relwid)
                    727:                                syserr("FILL_REL: fread A %d", i);
                    728:                        if (newreltype == M_HASH)
                    729:                                if (fread(junk, 1, 4, fp) != 4)
                    730:                                        syserr("FILL_REL: fread B");
                    731:                }
                    732:                else
                    733:                {
                    734: #                      ifdef xZTR2
                    735:                        if (tTf(36, 1))
                    736:                        {
                    737:                                printf("FILL_REL: stid ");
                    738:                                dumptid(&stid);
                    739:                                printf("FILL_REL: stidlim ");
                    740:                                dumptid(&stidlim);
                    741:                        }
                    742: #                      endif
                    743:                        i = get(sdesc, &stid, &stidlim, tup_buf, TRUE);
                    744: #                      ifdef xZTR2
                    745:                        if (tTf(36, 1))
                    746:                        {
                    747:                                printf("FILLREL: get %d ", i);
                    748:                                printup(sdesc, tup_buf);
                    749:                        }
                    750: #                      endif
                    751:                        if (i < 0)
                    752:                                syserr("FILL_REL: get %d", i);
                    753:                        if (i == 1)
                    754:                                break;
                    755:                }
                    756:                if (newreltype != M_ISAM)
                    757:                {
                    758:                        if ((i = insert(desc, &tid, tup_buf, chkdups)) < 0)
                    759:                                syserr("FILL_REL: insert %d", i);
                    760: #                      ifdef xZTR2
                    761:                        if (tTf(36, 2))
                    762:                        {
                    763:                                printf("FILL_REL: insert ");
                    764:                                printup(desc, tup_buf);
                    765:                                printf("FILL_REL: insert ret %d at", i);
                    766:                                dumptid(&tid);
                    767:                        }
                    768: #                      endif
                    769:                        continue;
                    770:                }
                    771:                if (anytups)
                    772:                        i = kcompare(desc, tup_buf, last_tup);
                    773:                else
                    774:                {
                    775:                        anytups = TRUE;
                    776:                        i = 1;
                    777:                }
                    778:                bmove(tup_buf, last_tup, desc->reldum.relwid);
                    779:                need = canonical(desc, tup_buf);
                    780:                if (i == 0 && need > space_left(Acc_head))
                    781:                {
                    782:                        /* spool out this tuple. will go on overflow page later */
                    783:                        if (spfp == NULL)
                    784:                        {
                    785:                                if ((spfp = fopen(Mod_info.spfile, "w")) == NULL)
                    786:                                        syserr("FILL_REL: fopen %.14s", Mod_info.spfile);
                    787:                                Mod_info.spflag = TRUE;
                    788:                        }
                    789:                        if (fwrite(tup_buf, 1, desc->reldum.relwid, spfp) != desc->reldum.relwid)
                    790:                                syserr("FILL_REL: putb spool");
                    791:                        continue;
                    792:                }
                    793:                j = (100 - F_fac) * MAXTUP / 100;
                    794:                if (j < need)
                    795:                        j = need;
                    796:                if (i != 0 && j > space_left(Acc_head))
                    797:                {
                    798:                        if (i = add_prim(desc, &tid))
                    799:                                syserr("FILL_REL: force ovflo %d", i);
                    800:                }
                    801:                tid.line_id = newlino(need);
                    802:                put_tuple(&tid, Acctuple, need);
                    803:                desc->reladds++;
                    804:        }
                    805:        if (sortit)
                    806:        {
                    807:                fclose(fp);
                    808:                unlink(Mod_info.outfile);
                    809:        }
                    810:        if (newreltype == M_ISAM)
                    811:        {
                    812:                if (i = pageflush(Acc_head))
                    813:                        syserr("fill_rel:pg clean %d", i);
                    814:                if (spfp != NULL)
                    815:                        fclose(spfp);
                    816:        }
                    817:        desc->reldum.reltups = desc->reladds;
                    818:        desc->reladds = 0;
                    819:        return (0);
                    820: }
                    821: 
                    822: 
                    823: bldindex(d)
                    824: register DESC  *d;
                    825: {
                    826:        register TID    *tid;
                    827:        register int    tmp;
                    828:        TID             tidx;
                    829:        struct accbuf   dirbuf;
                    830:        int             keywid, level, savespec, keyx[MAXDOM];
                    831:        int             offset, len;
                    832:        char            tuple[MAXTUP], temptup[MAXTUP], *key;
                    833:        long            pageid, start, stop, newstart, newstop;
                    834: 
                    835:        tid = &tidx;
                    836:        keywid = 0;
                    837:        for (tmp = 0; tmp < MAXDOM; tmp++)
                    838:                keyx[tmp] = 0;
                    839:        for (tmp = 1; tmp <= d->reldum.relatts; tmp++)
                    840:                if (d->relxtra[tmp] > 0)
                    841:                {
                    842:                        keyx[d->relxtra[tmp] - 1] = tmp;
                    843:                        keywid += d->relfrml[tmp] & I1MASK;
                    844:                }
                    845: 
                    846:        /* Determine the last page of the relation. This will
                    847:        ** only work if all pages have been written out. Fill_rel
                    848:        ** must guarantee that all pages have been written
                    849:        */
                    850:        level = 0;
                    851:        last_page(d, tid, 0);
                    852:        pluck_page(tid, &stop);
                    853:        start = 0;
                    854:        dirbuf.filedesc = d->relfp;
                    855:        dirbuf.rel_tupid = d->reltid.ltid;
                    856:        savespec = d->reldum.relspec;
                    857:        for (;;)
                    858:        {
                    859: #              ifdef xZTR2
                    860:                if (tTf(38, 7))
                    861:                        printf("isam: level %d\n", level);
                    862: #              endif
                    863:                dirbuf.ovflopg = start;
                    864:                dirbuf.mainpg = level;
                    865:                dirbuf.thispage = stop + 1;
                    866:                dirbuf.linetab[0] = (short) (dirbuf.firstup - (char *) &dirbuf);
                    867:                offset = dirbuf.linetab[0];
                    868:                dirbuf.bufstatus = BUF_DIRTY | BUF_DIRECT;
                    869: 
                    870:                dirbuf.nxtlino = 0;
                    871:                newstart = stop + 1;
                    872:                newstop = newstart;
                    873:                for (pageid = start; pageid <= stop; pageid++)
                    874:                {
                    875: #                      ifdef xZTR2
                    876:                        if (tTf(38, 8))
                    877:                                printf("isam:get key from %ld\n", pageid);
                    878: #                      endif
                    879:                        stuff_page(tid, &pageid);
                    880:                        tid->line_id = 0;
                    881:                        if (tmp = get(d, tid, tid, tuple, FALSE))
                    882:                        {
                    883:                                /*
                    884:                                ** If the relation is empty, then page 0 will
                    885:                                ** return AMINVL_ERR on a get(). Form a blank tuple
                    886:                                ** and use it to create a one tuple directory
                    887:                                */
                    888:                                if (pageid == 0 && tmp == AMINVL_ERR)
                    889:                                {
                    890:                                        clr_tuple(d, tuple);
                    891:                                }
                    892:                                else
                    893:                                {
                    894:                                        return (-2);
                    895:                                }
                    896:                        }
                    897: 
                    898:                        /*
                    899:                        ** If this is the first level then form the tuple
                    900:                        ** from the mainpage of the relation. Otherwise
                    901:                        ** the tuple is the first tuple of a directory page
                    902:                        ** and it is already correctly formed.
                    903:                        */
                    904:                        if (level == 0)
                    905:                        {
                    906:                                key = temptup;
                    907:                                for (tmp = 0; keyx[tmp] != 0; tmp++)
                    908:                                {
                    909:                                        len = d->relfrml[keyx[tmp]] & I1MASK;
                    910:                                        bmove(&tuple[d->reloff[keyx[tmp]]], key, len);
                    911:                                        key += len;
                    912:                                }
                    913:                                key = temptup;
                    914:                        }
                    915:                        else
                    916:                                key = tuple;
                    917: 
                    918:                        if (keywid > space_left(&dirbuf))
                    919:                        {
                    920:                                if (pageflush(&dirbuf))
                    921:                                        return (-3);
                    922:                                dirbuf.thispage++;
                    923:                                newstop = dirbuf.thispage;
                    924:                                dirbuf.ovflopg = pageid;
                    925:                                dirbuf.linetab[0] = (short) (dirbuf.firstup - (char *) &dirbuf);
                    926:                                offset = dirbuf.linetab[0];
                    927:                                dirbuf.bufstatus = BUF_DIRTY;
                    928:                                dirbuf.nxtlino = 0;
                    929:                        }
                    930:                        /* copy key to directory page */
                    931:                        bmove(key, (char *) &dirbuf + offset, keywid);
                    932: 
                    933:                        /* update next line number */
                    934:                        offset += keywid;
                    935:                        dirbuf.nxtlino++;
                    936:                        dirbuf.linetab[-dirbuf.nxtlino] = offset;
                    937:                }
                    938:                if (pageflush(&dirbuf))
                    939:                        return (-4);
                    940:                if (newstart == newstop)
                    941:                        break;
                    942:                d->reldum.relspec = abs(d->reldum.relspec);
                    943:                level++;
                    944:                start = newstart;
                    945:                stop = newstop;
                    946:        }
                    947:        d->reldum.relspec = savespec;
                    948:        d->reldum.relprim = newstart;
                    949:        return (0);
                    950: }
                    951: /*
                    952: **     UNSPOOL -- Take tuples saved in spool file and insert them
                    953: **             in new relation.  This is only for ISAM relations.
                    954: */
                    955: 
                    956: unspool(desc)
                    957: register DESC  *desc;
                    958: {
                    959:        register int    i;
                    960:        TID             tid;
                    961:        char            tup_buf[MAXTUP];
                    962:        FILE            *spfp;
                    963: 
                    964:        if (Mod_info.spflag)
                    965:        {
                    966:                if ((spfp = fopen(Mod_info.spfile, "r")) == NULL)
                    967:                        syserr("UNSPOOL: fopen spool");
                    968:                while ((i = fread(tup_buf, 1, desc->reldum.relwid, spfp)) == desc->reldum.relwid)
                    969:                        if ((i = insert(desc, &tid, tup_buf, FALSE)) < 0)
                    970:                                syserr("UNSPOOL: insert %.14s %d", desc->reldum.relid, i);
                    971:                if (i != 0)
                    972:                        syserr("UNSPOOL: read %d", i);
                    973:                fclose(spfp);
                    974:                unlink(Mod_info.spfile);
                    975:        }
                    976:        desc->reldum.reltups += desc->reladds;
                    977:        desc->reladds = 0;
                    978:        return (0);
                    979: }
                    980: /*
                    981: **     FILL_BATCH -- Create and fill a batch file containing the
                    982: **             updates for the system catalog so that MODIFY will
                    983: **             be recoverable if the system crashes.
                    984: */
                    985: 
                    986: fill_batch(odesc, desc)
                    987: DESC           *odesc;
                    988: register DESC  *desc;
                    989: {
                    990:        register DESC           *dessys;
                    991:        register int            i;
                    992:        struct relation         reltup, rkey;
                    993:        TID                     tid, lotid, hitid;
                    994:        struct attribute        atttup, akey;
                    995:        int                     j;
                    996:        char                    prebatch[MAXNAME + 4], modbatch[MAXNAME + 4];
                    997: 
                    998:        if (bequal(desc->reldum.relid, "relation    ", 12))
                    999:        {
                   1000:                clearkeys(desc);
                   1001:                setkey(desc, &rkey, desc->reldum.relid, RELID);
                   1002:                setkey(desc, &rkey, desc->reldum.relowner, RELOWNER);
                   1003:                if (i = getequal(desc, &rkey, &reltup, &tid))
                   1004:                        syserr("FILL_BATCH: geteq rel rel %d", i);
                   1005:                bmove(&tid, &desc->reltid, sizeof desc->reltid);
                   1006:        }
                   1007:        else
                   1008:                bmove(&odesc->reltid, &desc->reltid, sizeof desc->reltid);
                   1009:        resetacc(Acc_head);
                   1010:        concat(MOD_PREBATCH, Fileset, prebatch);
                   1011:        close(creat(prebatch, FILEMODE));
                   1012:        if ((Batch_fp = open(prebatch, 2)) < 0)
                   1013:                syserr("FILL_BATCH: open %.14s %d", prebatch, Batch_fp);
                   1014:        smove(Fileset, Batchbuf.file_id);
                   1015:        Batch_cnt = 0;
                   1016:        wrbatch(desc, sizeof *desc);
                   1017:        if (bequal(desc->reldum.relid, "attribute   ", 12))
                   1018:                dessys = desc;
                   1019:        else
                   1020:                dessys = &Admin.adattd;
                   1021:        clearkeys(dessys);
                   1022:        setkey(dessys, &akey, desc->reldum.relid, ATTRELID);
                   1023:        setkey(dessys, &akey, desc->reldum.relowner, ATTOWNER);
                   1024:        if (i = find(dessys, EXACTKEY, &lotid, &hitid, &akey))
                   1025:                syserr("FILL_BATCH: find %d", i);
                   1026:        j = desc->reldum.relatts;
                   1027:        while(!(i = get(dessys, &lotid, &hitid, &atttup, TRUE)) && j > 0)
                   1028:                if (!kcompare(dessys, &akey, &atttup))
                   1029:                {
                   1030:                        j--;
                   1031:                        atttup.attxtra = desc->relxtra[atttup.attid];
                   1032:                        wrbatch(&lotid, sizeof lotid);
                   1033:                        wrbatch(&atttup, sizeof atttup);
                   1034:                }
                   1035:        if (i < 0 || j > 0)
                   1036:                syserr("FILL_BATCH: get att %d count %d", i, j);
                   1037:        /* get rid of attribute pages */
                   1038:        cleanrel(dessys);
                   1039:        flushbatch();
                   1040:        close(Batch_fp);
                   1041:        concat(MODBATCH, Fileset, modbatch);
                   1042:        if (link(prebatch, modbatch) == -1)
                   1043:                syserr("FILL_BATCH: can't link %.14s %.14s",
                   1044:                        prebatch, modbatch);
                   1045:        unlink(prebatch);
                   1046:        return (0);
                   1047: 
                   1048: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.