160 lines
2.6 KiB
Text
160 lines
2.6 KiB
Text
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}
|