|
|
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.