create new record get a page with enough free space check existing pages for free space create a new emtpy page alloc a record on that page increment number of records on this page update free space pointer write to record load the page into memory find the page on disk put the page in memory lock the page get the memory address of the record look up the record offset in the slot directory write to that record update log update lsn on page read record load the page into memory get the address of the record read that record begin xaction commit xaction flush unlock abort xaction delete page from memory unlock ================================================================================ recordid memory.ralloc(int xid, size_t size) { for each page in the page table // page table are pages in RAM if locked, continue // context switch here SUCKS lock page break if freeSpace(page) >= size free page if no free page create a new page and lock and load return (recordid) page.recordAllocate(page, size) } void page.writeRecord(recordid rid, void *data) { assert page locked and loaded if xid and recordid is in hash table, do nothing else make shadow record memcpy() } void *page.readRecord(recordid rid, void *buff) { make sure page is loaded memcpy() return pointer } commitXaction(int xid) { for each page that this xid has locked unlock page if pin count of page == 0 flush } abortXaction(int xid) { for each locked page restore shadow records unlock page } ================================================================================ transactional.c Tread Tbegin Tcommit Tabort operations.h Tset Tdec Tinc struct page { void *memAddr long lsn semaphore lock } bufferManager.c struct page loadPage(pageid) flushPage(struct page) // maybe take pageid dropPage(struct page) // maybe take pageid bufTransCommit(xid) // call flush and dropPage on page buffer bufTransAbort(xid) // call flush and dropPage on page buffer pin unpin page.c rid ralloc(int size) // depends on bufferManager writeRecord(rid, data) readRecord(rid, buff) recovery.c logger.c constants.h ============================== buffer needs xid => ( pages ) (dirty pages) page, first write LSN page needs xid => ( recordids ) xid,recordid => data ================ Testing in main.c we can write something to the effect of begin write for(;;) printf("looping"); commit this way, when we see that "looping is printing, we can purposefully crash the program with control-c not sure that this is anydifferent than having main.c {begin, write, exit}