/*! * \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; }
/** * Invalidate any buffers that are duplicates of abuf. Duplicate buffers * can appear if a read transaction reads a page that is dirty, then that * dirty page is synced. The read transaction will skip over the dirty page, * and create a new buffer, and when the dirty page is synced, it will be * identical (except for contents) to the read-transaction buffer. */ static void DedupBuffer(struct buffer *abuf) { struct buffer *tb; for (tb = phTable[pHash(abuf->page)]; tb; tb = tb->hashNext) { if (tb->page == abuf->page && tb != abuf && tb->file == abuf->file && tb->dbase == abuf->dbase) { tb->file = BADFID; Dlru(tb); } } }
/*! * \brief Mark an \p fid as invalid. */ int udisk_Invalidate(struct ubik_dbase *adbase, afs_int32 afid) { struct buffer *tb; int i; for (i = 0, tb = Buffers; i < nbuffers; i++, tb++) { if (tb->file == afid) { tb->file = BADFID; Dlru(tb); } } return 0; }
/*! * \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; }
/*! * \brief Flush all modified buffers. */ static int DAbort(struct ubik_trans *atrans) { int i; struct buffer *tb; tb = Buffers; for (i = 0; i < nbuffers; i++, tb++) { if (tb->dirty) { tb->dirty = 0; tb->file = BADFID; Dlru(tb); } } return 0; }
/*! * \brief Zap truncated pages. */ static int DTrunc(struct ubik_trans *atrans, afs_int32 fid, afs_int32 length) { afs_int32 maxPage; struct buffer *tb; int i; struct ubik_dbase *dbase = atrans->dbase; maxPage = (length + UBIK_PAGESIZE - 1) >> UBIK_LOGPAGESIZE; /* first invalid page now in file */ for (i = 0, tb = Buffers; i < nbuffers; i++, tb++) { if (tb->page >= maxPage && tb->file == fid && tb->dbase == dbase) { tb->file = BADFID; Dlru(tb); } } return 0; }