1: # include "../ingres.h" 2: # include "../access.h" 3: # include "../aux.h" 4: # include "../lock.h" 5: # include "../unix.h" 6: 7: 8: /* 9: ** access method buffers and other data areas for buffer maintenance 10: */ 11: 12: struct accbuf Acc_buf[NACCBUFS]; /* the buffers */ 13: struct accbuf *Acc_head; /* head of usage list */ 14: struct accbuf *Acc_tail; /* tail of usage list */ 15: struct lockreq Lock; 16: 17: /* 18: ** structs for admin file data 19: */ 20: 21: struct admin Admin; 22: 23: /* 24: ** global flag indicating if access methods 25: ** have been initialized. 26: */ 27: 28: int Acc_init = FALSE; 29: 30: /* tTf flag 80 TTF resetacc()*/ 31: 32: resetacc(buf) 33: struct accbuf *buf; 34: 35: /* 36: ** Flush the indicated page and reset all 37: ** important information including the name 38: */ 39: 40: { 41: register struct accbuf *b; 42: register int i; 43: 44: b = buf; 45: if (b == 0) 46: b = Acc_head; 47: # ifdef xATR3 48: if (tTf(80, 0)) 49: printf("RESETACC: (%u=%s)\n", b, locv(b->rel_tupid)); 50: # endif 51: 52: i = pageflush(b); /* write the page if necessary */ 53: b->rel_tupid = -1; 54: b->filedesc = -1; 55: b->thispage = -1; 56: b->bufstatus = 0; 57: return (i); 58: } 59: 60: 61: /* 62: ** initialize access method data areas 63: */ 64: 65: /* tTf flag 81 TTF acc_init() */ 66: 67: acc_init() 68: { 69: register int i; 70: register struct accbuf *last; 71: register struct accbuf *b; 72: struct stat stbuf; 73: extern int errno; 74: 75: # ifdef xATR3 76: tTfp(81, 0, "ACC_INIT=%d\n", Acc_init); 77: # endif 78: 79: if (Acc_init) 80: return (0); /* already initialized */ 81: last = 0; 82: for (b = Acc_buf; b < &Acc_buf[NACCBUFS]; ) 83: { 84: resetacc(b); 85: b->modb = last; 86: last = b; 87: b++; 88: last->modf = b; 89: } 90: last->modf = 0; 91: Acc_head = Acc_buf; 92: Acc_tail = last; 93: 94: /* get the admin file */ 95: readadmin(); 96: 97: /* 98: ** Set up locking information. If the database has concurrency 99: ** control then Lockrel = TRUE and the concurrency device will 100: ** be opened for writing. If there is no concurrency for the 101: ** data base or if the lock device isn't installed, then Alockdes 102: ** = -1 and no locking will (or can) occure. 103: */ 104: Lockrel = (Admin.adhdr.adflags & A_DBCONCUR) != 0; 105: if (Lockrel && Alockdes < 0) 106: Alockdes = open("/dev/ingreslock", 1); 107: errno = 0; /* clear in case /dev/ingreslock isn't available */ 108: Acclock = TRUE; 109: stat(".", &stbuf); 110: bmove(&stbuf, Lock.dbnode, 4); 111: 112: Acc_init = TRUE; 113: } 114: 115: 116: /* 117: ** place buffer at top of LRU list 118: */ 119: 120: top_acc(buf) 121: struct accbuf *buf; 122: { 123: register struct accbuf *b; 124: 125: b = buf; 126: 127: if (b == Acc_head) 128: return (0); 129: if (b == Acc_tail) 130: Acc_tail = b->modb; 131: else 132: b->modf->modb = b->modb; 133: b->modb->modf = b->modf; 134: Acc_head->modb = b; 135: b->modf = Acc_head; 136: Acc_head = b; 137: b->modb = 0; 138: return (0); 139: } 140: 141: flush_rel(d1, resetflag) 142: struct descriptor *d1; 143: int resetflag; 144: 145: /* 146: ** Flush_rel -- flush all pages associated with the relation 147: ** described by the descriptor. If resetflag is TRUE, 148: ** then the buffers are reset so the pages will not be 149: ** found on subsequent calls to find_page(). 150: ** 151: ** Returns "or'ed" result from calls to pageflush. 152: */ 153: 154: { 155: register struct descriptor *d; 156: register struct accbuf *b; 157: register int i; 158: 159: d = d1; 160: i = 0; 161: 162: for (b = Acc_head; b != NULL; b = b->modf) 163: { 164: if (d->reltid == b->rel_tupid) 165: { 166: if (resetflag) 167: i |= resetacc(b); 168: else 169: i |= pageflush(b); 170: } 171: } 172: 173: return (i); 174: } 175: 176: 177: /* 178: ** CHOOSE_BUF -- Try to find an empty buffer for assignment. 179: ** If there is no empty buffer, pick the last buffer 180: ** in the LRU queue and make sure it is flushed. 181: ** 182: ** Choose_buf guarantees that the buffer will be reset 183: ** if it was used previously for a different relation. 184: */ 185: 186: /* tTf flag 82.8 TTF choose_buf() */ 187: 188: struct accbuf *choose_buf(dx, pageid) 189: struct descriptor *dx; 190: long pageid; 191: 192: /* 193: ** Choose_buf -- choose a buffer for use with the given relation on 194: ** the given page. The current algorithm is to allow only one buffer 195: ** per relation. If a relation does not have a buffer, it is given a 196: ** free one (if any) or else the Least Recently Used. 197: */ 198: 199: { 200: register struct accbuf *b, *free; 201: register struct descriptor *d; 202: struct accbuf *mine; 203: 204: d = dx; 205: free = mine = NULL; 206: 207: for (b = Acc_head; b != 0; b = b->modf) 208: { 209: if (b->rel_tupid == -1) 210: free = b; 211: else 212: if (d->reltid == b->rel_tupid) 213: { 214: if (pageid == b->thispage) 215: { 216: if (d->relopn < 0) 217: b->filedesc = d->relfp; 218: return (b); 219: } 220: mine = b; 221: } 222: } 223: 224: /* 225: ** "Free" and "Mine" now reflect the current state of the buffers. 226: ** There is no buffer with the currently requested page 227: */ 228: 229: # ifdef xATR3 230: tTfp(82, 9, "choosebuf free %l,mine %l\n", free, mine); 231: # endif 232: 233: /* no current buffer. Choose a free one or LRU */ 234: if (free == NULL) 235: free = resetacc(Acc_tail) ? NULL : Acc_tail; /* error if can't reset the LRU */ 236: if (free) 237: { 238: /* copy relevent material (in this order in case of rubout */ 239: free->filedesc = d->relfp; 240: free->rel_tupid = d->reltid; 241: } 242: 243: # ifdef xATR1 244: if (tTf(82, 8)) 245: printf("choosebuf:rets %l\n", free); 246: # endif 247: return (free); 248: } 249: 250: /* 251: ** ACC_CLOSE -- flush any buffers left around 252: ** and then close the files for relation & attribute. 253: ** The relation and attribute relation are normally left open 254: ** until the end of an INGRES session but must be closed 255: ** and re-opened in the dbu's whenever a new overlay is loaded. 256: */ 257: 258: acc_close() 259: { 260: register int i; 261: 262: if (i = pageflush(0)) 263: syserr("acc_close: pageflush %d, i"); 264: close(Admin.adreld.relfp); 265: close(Admin.adattd.relfp); 266: Admin.adreld.relopn = Admin.adattd.relopn = 0; 267: if (Alockdes >= 0) 268: close(Alockdes); 269: Alockdes = -1; 270: Acc_init = FALSE; 271: return (0); 272: }