1: # include "../ingres.h" 2: # include "../aux.h" 3: # include "../tree.h" 4: # include "../symbol.h" 5: # include "decomp.h" 6: 7: 8: 9: struct desc_tab 10: { 11: int relnum; /* relation number */ 12: char dtmode; /* status of descriptor */ 13: char dtpos; /* position of last access */ 14: struct descriptor desc; /* descriptor */ 15: }; 16: 17: /* Defined constants for dtmode field above */ 18: # define DTALLOC 0 /* descriptor allocated */ 19: # define DTREL 1 /* has been openr'd -1 */ 20: # define DTATTS 2 /* has rel+atts but not opened */ 21: # define DTREAD 3 /* currently open for reading */ 22: # define DTWRITE 4 /* currently open for writing */ 23: 24: 25: 26: /* Allocation of descriptors */ 27: struct desc_tab Desc[MAXRELN]; /* descriptors available for use */ 28: 29: /* Globals which count #files open and maximum # of files which can be open */ 30: int Dfiles, Dopnfiles; 31: 32: 33: /* 34: ** OPENRS -- routines associated with maintaining the range table for decomp 35: ** 36: ** openrs(root) -- fill range table info about each relation. 37: ** 38: ** closers() -- close all variables in range table. 39: ** 40: ** openr1(varno) -- fill range table for a particular relation. 41: ** 42: ** closer1(varno) -- close a particular relation. 43: ** 44: ** readopen(varno) -- open a variable for reading. returns descriptor. 45: ** 46: ** writeopen(varno) -- open a variable for writing. returns descriptor. 47: ** 48: ** initdesc() -- initialize the descriptor cache. 49: ** 50: ** reldescrip(varno) -- returns descriptor for var (has rel/atts but might not be open). 51: ** 52: ** desc_get(relnum, flag) -- finds a desc_tab & alloctes it for relnum. 53: ** 54: ** desc_lru() -- returns least recently used desc_tab. 55: ** 56: ** desc_top(desc_tab) -- makes desc_tab most recently used. 57: ** 58: ** desc_last(desc_tab) -- makes desc_tab the least recently used. 59: */ 60: 61: 62: initdesc(mode) 63: int mode; 64: 65: /* 66: ** Initdesc -- initialize descriptors for range table 67: */ 68: 69: { 70: register struct desc_tab *dt; 71: register int i; 72: extern int Equel; 73: 74: 75: for (dt = Desc, i = 0; dt <= &Desc[MAXRELN - 1]; dt++, i++) 76: { 77: dt->dtmode = DTALLOC; 78: dt->relnum = -2; /* unused relnum value */ 79: dt->dtpos = i; /* lru order */ 80: } 81: 82: /* 83: ** Determine number of available file descriptors. 84: ** The answer will depend on whether this is decomp 85: ** alone or decomp+ovqp, and whether it is an update 86: ** and whether this is an equel program. 87: */ 88: 89: Dfiles = files_avail(mode); 90: Dopnfiles = 0; 91: } 92: 93: 94: openrs(root) 95: struct querytree *root; 96: 97: /* 98: ** Openrs -- open source relations for query. Fill values 99: ** in range table. 100: */ 101: 102: { 103: register struct querytree *r; 104: register int map, i; 105: struct descriptor *openr1(); 106: 107: r = root; 108: map = ((struct qt_root *)r)->lvarm | ((struct qt_root *)r)->rvarm; 109: 110: # ifdef xDTR1 111: if (tTf(2, 0)) 112: printf("OPENRS-root:%l,map:%o\n", r, map); 113: # endif 114: 115: for (i = 0; i < MAXRANGE; i++) 116: if (map & (01 << i)) 117: openr1(i); 118: 119: } 120: 121: 122: 123: closers() 124: 125: /* 126: ** Close all open relations. 127: ** If any relations were created but never 128: ** opened, destroy them. The only 129: ** situation under which that can occure 130: ** is when a rub-out occures at an 131: ** in oportune moment or when an error 132: ** occures in ovqp. 133: */ 134: 135: { 136: register int i; 137: register struct desc_tab *dt; 138: 139: 140: for (dt = Desc; dt <= &Desc[MAXRELN - 1]; dt++) 141: desc_close(dt); 142: 143: /* destroy any temps */ 144: initp(); /* init parameters vector for destroys */ 145: while (i = rnum_last()) 146: dstr_mark(i); 147: dstr_flush(1); /* call destroy with rel names */ 148: } 149: 150: 151: 152: struct descriptor *openr1(var) 153: int var; 154: 155: /* 156: ** Openr1 -- open relation to get relation relation tuple 157: ** 158: ** This will not open the relation for reading -- only 159: ** for getting the first part of the descriptor filled 160: */ 161: 162: { 163: register struct desc_tab *dt; 164: register struct rang_tab *rp; 165: register struct descriptor *d; 166: int i; 167: struct desc_tab *desc_get(); 168: 169: rp = &Rangev[var]; 170: 171: # ifdef xDTR1 172: if (tTf(2, 2)) 173: printf("openr1: var %d (%s)\t", var, rnum_convert(rp->relnum)); 174: # endif 175: 176: dt = desc_get(rp->relnum, TRUE); 177: 178: if (dt->dtmode == DTALLOC) 179: { 180: if (i = openr(&dt->desc, -1, rnum_convert(rp->relnum))) 181: syserr("openr1 open %d %s", i, rnum_convert(rp->relnum)); 182: dt->dtmode = DTREL; 183: } 184: 185: # ifdef xDTR1 186: if (tTf(2, 2)) 187: printf("tups=%s\n", locv(dt->desc.reltups)); 188: # endif 189: 190: d = &dt->desc; 191: 192: rp->rtspec = d->relspec; 193: rp->rtstat = d->relstat; 194: rp->rtwid = d->relwid; 195: rp->rtcnt = d->reltups; 196: 197: return (d); 198: } 199: 200: 201: closer1(var) 202: int var; 203: 204: /* 205: */ 206: 207: { 208: register struct desc_tab *dt; 209: register struct rang_tab *rp; 210: register int i; 211: struct desc_tab *desc_get(); 212: 213: i = var; 214: rp = &Rangev[i]; 215: 216: # ifdef xDTR1 217: if (tTf(2, 4)) 218: printf("closer1:var %d (%s)\n", i, rnum_convert(rp->relnum)); 219: # endif 220: if (dt = desc_get(rp->relnum, FALSE)) 221: { 222: 223: /* currently a descriptor for rel */ 224: desc_close(dt); 225: 226: dt->relnum = -2; 227: desc_last(dt); 228: 229: } 230: } 231: 232: 233: struct descriptor *readopen(var) 234: int var; 235: 236: /* 237: */ 238: 239: { 240: register struct desc_tab *dt; 241: struct desc_tab *desc_get(); 242: 243: /* get descv for the relation */ 244: dt = desc_get(Rangev[var].relnum, TRUE); 245: 246: if (!(dt->dtmode == DTREAD || dt->dtmode == DTWRITE)) 247: { 248: /* not open for reading or writing */ 249: openup(dt, var, 0); /* open for reading */ 250: } 251: 252: return (&dt->desc); 253: } 254: 255: 256: struct descriptor *writeopen(var) 257: int var; 258: 259: /* 260: */ 261: 262: { 263: register struct desc_tab *dt; 264: struct desc_tab *desc_get(); 265: /* get descv for the relation */ 266: dt = desc_get(Rangev[var].relnum, TRUE); 267: 268: if (dt->dtmode != DTWRITE) 269: { 270: /* not open for writing */ 271: openup(dt, var, 2); /* open for reading */ 272: } 273: 274: return (&dt->desc); 275: } 276: 277: 278: struct descriptor *specopen(relnum) 279: int relnum; 280: 281: /* 282: ** Specopen -- open for writing not associated with any variable 283: */ 284: 285: { 286: register struct desc_tab *dt; 287: struct desc_tab *desc_get(); 288: 289: dt = desc_get(relnum, TRUE); 290: 291: if (dt->dtmode != DTWRITE) 292: openup(dt, -1, 2); 293: 294: return (&dt->desc); 295: } 296: 297: 298: specclose(relnum) 299: int relnum; 300: { 301: register struct desc_tab *dt; 302: struct desc_tab *desc_get(); 303: 304: if (dt = desc_get(relnum, FALSE)) 305: { 306: desc_close(dt); 307: desc_last(dt); 308: dt->relnum = -2; 309: } 310: } 311: 312: 313: openup(dt1, varno, mode) 314: struct desc_tab *dt1; 315: int varno; 316: int mode; 317: 318: /* 319: ** Openup -- make sure that the given descriptor is open 320: ** suitably for reading or writing. 321: */ 322: 323: { 324: register struct desc_tab *dt; 325: register int md, openmd; 326: int i; 327: 328: /* quick check to handle typical case of rel being already open */ 329: md = mode; 330: dt = dt1; 331: if ((md != 2 && dt->dtmode == DTREAD) || dt->dtmode == DTWRITE) 332: return; 333: 334: /* relation not opened correctly */ 335: switch (dt->dtmode) 336: { 337: 338: case DTALLOC: 339: /* 340: ** Descriptor allocated but nothing else. If this 341: ** is for a variable then use openr1 to get range table 342: ** info. Else open directly. 343: */ 344: if (varno < 0) 345: { 346: /* open unassociated with a range table variable */ 347: openmd = md ? 2 : 0; 348: bmove(rnum_convert(dt->relnum), dt->desc.relid, MAXNAME); 349: break; 350: } 351: 352: /* open for range table variable */ 353: openr1(varno); 354: 355: /* now fall through to DTREL case */ 356: 357: case DTREL: 358: /* relation relation tuple present but nothing else */ 359: openmd = md ? -3 : -2; /* open -2 for read, -3 for write */ 360: break; 361: 362: case DTATTS: 363: /* relation & attributes filled but relation closed */ 364: openmd = md ? -5 : -4; 365: break; 366: case DTREAD: 367: /* relation open for reading but we need to write */ 368: desc_close(dt); 369: 370: openmd = -5; 371: break; 372: 373: default: 374: syserr("openup:bad md %d", dt->dtmode); 375: } 376: 377: /* close a previous file if necessary */ 378: if (Dopnfiles == Dfiles) 379: desc_victum(); /* close oldest file */ 380: 381: /* now open relation */ 382: if (i = openr(&dt->desc, openmd, dt->desc.relid)) 383: syserr("openup:openr %d,%d,%.12s,%s", i, openmd, dt->desc.relid, rnum_convert(dt->relnum)); 384: Dopnfiles++; 385: 386: /* update mode of descriptor */ 387: dt->dtmode = md ? DTWRITE : DTREAD; 388: } 389: 390: 391: 392: struct desc_tab *desc_get(relnum, flag) 393: int relnum; 394: int flag; 395: 396: /* 397: */ 398: 399: { 400: register struct desc_tab *dt, *ret; 401: struct desc_tab *desc_lru(); 402: 403: ret = NULL; 404: 405: /* search for one currently allocated */ 406: for (dt = &Desc[0]; dt <= &Desc[MAXRELN-1]; dt++) 407: { 408: if (dt->relnum == relnum) 409: { 410: ret = dt; 411: # ifdef xDTR1 412: if (tTf(2, 3)) 413: printf("found desc for %d\n", relnum); 414: # endif 415: break; 416: } 417: } 418: 419: if (ret == NULL && flag) 420: { 421: /* get a victum and deallocate desc */ 422: ret = desc_lru(); 423: 424: /* deallocate */ 425: # ifdef xDTR1 426: if (tTf(2, 5)) 427: printf("trading %d for %d\n", ret->relnum, relnum); 428: # endif 429: desc_close(ret); 430: 431: /* allocate */ 432: ret->relnum = relnum; 433: ret->dtmode = DTALLOC; 434: } 435: 436: if (ret != NULL) 437: desc_top(ret); 438: 439: return (ret); 440: } 441: 442: 443: 444: /* 445: ** For text space reasons only, the close relation routine varies 446: ** between decomp and decomp70. In decomp, the relation is opened 447: ** only for reading and never for writing thus inpcloser() can be 448: ** called. For decomp70 closer() must be called. If there were no 449: ** text space shortage, then closer() could always be called. 450: ** The routine init_decomp() assigned the value to Des_closefunc. 451: */ 452: extern int (*Des_closefunc)(); /* either &inpcloser or &closer */ 453: 454: desc_close(dt1) 455: struct desc_tab *dt1; 456: { 457: register struct desc_tab *dt; 458: register int i; 459: 460: dt = dt1; 461: 462: if (dt->dtmode == DTREAD || dt->dtmode == DTWRITE) 463: { 464: if (i = (*Des_closefunc)(&dt->desc)) 465: syserr("desc_close:closer %d,%.12s", i, dt->desc.relid); 466: Dopnfiles--; 467: dt->dtmode = DTATTS; 468: } 469: } 470: 471: 472: 473: 474: desc_top(dt1) 475: struct desc_tab *dt1; 476: 477: /* 478: ** Desc_top -- make the desc_tab entry "dtx" the most recently used. 479: */ 480: 481: { 482: register struct desc_tab *dt, *dx; 483: register int oldpos; 484: 485: dt = dt1; 486: 487: if ((oldpos = dt->dtpos) != 0) 488: { 489: /* descriptor isn't currently top */ 490: for (dx = Desc; dx <= &Desc[MAXRELN-1]; dx++) 491: if (dx->dtpos < oldpos) 492: dx->dtpos++; 493: 494: /* make descriptor first */ 495: dt->dtpos = 0; 496: } 497: } 498: 499: 500: struct desc_tab *desc_last(dt1) 501: struct desc_tab *dt1; 502: 503: /* 504: ** Desc_last -- make the desc_tab entry "dtx" the least recently used. 505: */ 506: 507: { 508: register struct desc_tab *dt, *dx; 509: register int oldpos; 510: 511: dt = dt1; 512: 513: oldpos = dt->dtpos; 514: for (dx = Desc; dx <= &Desc[MAXRELN-1]; dx++) 515: if (dx->dtpos > oldpos) 516: dx->dtpos--; 517: 518: /* make descriptor last */ 519: dt->dtpos = MAXRELN - 1; 520: } 521: 522: 523: 524: struct desc_tab *desc_lru() 525: 526: /* 527: ** Desc_lru -- return least recently used descriptor 528: */ 529: 530: { 531: register struct desc_tab *dx; 532: 533: for (dx = Desc; dx <= &Desc[MAXRELN-1]; dx++) 534: { 535: if (dx->dtpos == MAXRELN - 1) 536: return (dx); 537: } 538: syserr("desc_lru:no lru"); 539: } 540: 541: 542: desc_victum() 543: { 544: register struct desc_tab *dt, *old; 545: 546: old = NULL; 547: for (dt = &Desc[0]; dt <= &Desc[MAXRELN-1]; dt++) 548: { 549: if (dt->dtmode == DTWRITE || dt->dtmode == DTREAD) 550: { 551: if (old == NULL || dt->dtpos > old->dtpos) 552: old = dt; 553: } 554: } 555: 556: if (old == NULL) 557: syserr("desc_victum:no victum %d,%d", Dopnfiles, Dfiles); 558: desc_close(old); 559: }