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

Defined functions

bldindex defined in line 784; used 1 times
fill_batch defined in line 952; used 1 times
fill_rel defined in line 635; used 1 times
getfill defined in line 433; used 1 times
getkeys defined in line 261; used 1 times
make_newrel defined in line 531; used 1 times
modseqkey defined in line 391; used 1 times
sortrel defined in line 582; used 1 times
unspool defined in line 919; used 1 times

Defined variables

F_fac defined in line 45; used 10 times
Mn_pages defined in line 45; used 9 times
Mod_info defined in line 85; used 27 times
Modtab defined in line 60; used 1 times
Mx_pages defined in line 45; used 9 times

Defined struct's

mod_info defined in line 76; used 2 times
  • in line 85(2)
modtab defined in line 47; used 6 times
Last modified: 1995-02-12
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5772
Valid CSS Valid XHTML 1.0 Strict