Annotation of 42BSD/ingres/source/dbu/modify.c, revision 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.2     5/31/83)
        !            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:                        F_fac = atoi(p1);
        !           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:                        Mn_pages = atoi(p1);
        !           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:                        Mx_pages = atoi(p1);
        !           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.