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