/*! * \brief Create a new slot for a particular dbase page. */ static struct buffer * newslot(struct ubik_dbase *adbase, afs_int32 afid, afs_int32 apage) { /* Find a usable buffer slot */ afs_int32 i; struct buffer *pp, *tp; pp = 0; /* last pure */ for (i = 0, tp = LruBuffer; i < nbuffers; i++, tp = tp->lru_next) { if (!tp->lockers && !tp->dirty) { pp = tp; break; } } if (pp == 0) { /* There are no unlocked buffers that don't need to be written to the disk. */ ubik_print ("Ubik: Internal Error: Unable to find free buffer in ubik cache\n"); return NULL; } /* Now fill in the header. */ pp->dbase = adbase; pp->file = afid; pp->page = apage; FixupBucket(pp); /* move to the right hash bucket */ Dmru(pp); return pp; }
/*! * \brief Get a pointer to a particular buffer. */ static char * DRead(struct ubik_trans *atrans, afs_int32 fid, int page) { /* Read a page from the disk. */ struct buffer *tb, *lastbuffer, *found_tb = NULL; afs_int32 code; struct ubik_dbase *dbase = atrans->dbase; calls++; lastbuffer = LruBuffer->lru_prev; /* Skip for write transactions for a clean page - this may not be the right page to use */ if (MatchBuffer(lastbuffer, page, fid, atrans) && (atrans->type == UBIK_READTRANS || lastbuffer->dirty)) { tb = lastbuffer; tb->lockers++; lastb++; return tb->data; } for (tb = phTable[pHash(page)]; tb; tb = tb->hashNext) { if (MatchBuffer(tb, page, fid, atrans)) { if (tb->dirty || atrans->type == UBIK_READTRANS) { found_tb = tb; break; } /* Remember this clean page - we might use it */ found_tb = tb; } } /* For a write transaction, use a matching clean page if no dirty one was found */ if (found_tb) { Dmru(found_tb); found_tb->lockers++; return found_tb->data; } /* can't find it */ tb = newslot(dbase, fid, page); if (!tb) return 0; memset(tb->data, 0, UBIK_PAGESIZE); tb->lockers++; code = (*dbase->read) (dbase, fid, tb->data, page * UBIK_PAGESIZE, UBIK_PAGESIZE); if (code < 0) { tb->file = BADFID; Dlru(tb); tb->lockers--; ubik_print("Ubik: Error reading database file: errno=%d\n", errno); return 0; } ios++; /* Note that findslot sets the page field in the buffer equal to * what it is searching for. */ return tb->data; }
/*! * \brief Get a pointer to a particular buffer. */ static char * DRead(struct ubik_trans *atrans, afs_int32 fid, int page) { /* Read a page from the disk. */ struct buffer *tb, *lastbuffer; afs_int32 code; struct ubik_dbase *dbase = atrans->dbase; calls++; lastbuffer = LruBuffer->lru_prev; if (MatchBuffer(lastbuffer, page, fid, atrans)) { tb = lastbuffer; tb->lockers++; lastb++; return tb->data; } for (tb = phTable[pHash(page)]; tb; tb = tb->hashNext) { if (MatchBuffer(tb, page, fid, atrans)) { Dmru(tb); tb->lockers++; return tb->data; } } /* can't find it */ tb = newslot(dbase, fid, page); if (!tb) return 0; memset(tb->data, 0, UBIK_PAGESIZE); tb->lockers++; code = (*dbase->read) (dbase, fid, tb->data, page * UBIK_PAGESIZE, UBIK_PAGESIZE); if (code < 0) { tb->file = BADFID; Dlru(tb); tb->lockers--; ubik_print("Ubik: Error reading database file: errno=%d\n", errno); return 0; } ios++; /* Note that findslot sets the page field in the buffer equal to * what it is searching for. */ return tb->data; }