|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.