背景
这是数据库大作业。本来过了deadline发出来过一次,结果突然老师又给大家时间改作业,我就又撤回去了。现在分数出来了,我可以再把代码放出来了。
说明
python版本3.5。
四个已知输入是四个操作序列,b代表开始,e代表结束,r是读,w是写。数字代表事务编号,括号里的字母是事务所使用的资源。输出四个输入序列对应的数据库内部执行情况。本身就是个模拟性质的代码,也就没啥鲁棒性,还要啥自行车啊。
代码
我注释写得挺全的,就不做额外解释了。
#classes, notice that tid is also a string
class transaction_class:
def __init__(self):
self.tid=[]
self.state=""
self.blocked_by=""
class lock_class:
def __init__(self):
self.tid=[]#there might be more than one read locks
self.item=""
self.mode=""
self.num_of_reads=0
#lists
input_list=["b","1",";","r","1","(","Y",")",";","r","1","(","Z",")",";","b","2",";","r","2","(","Y",")",";","b","3",";","r","3","(","Y",")",";","w","1","(","Z",")",";","w","3","(","Y",")",";","w","2","(","Y",")",";","r","2","(","X",")",";","e","1",";","e","3",";","w","2","(","X",")",";","e","2",";"]
input_list2=["b","1",";","r","1","(","Y",")",";","w","1","(","Y",")",";","r","1","(","Z",")",";","b","2",";","r","2","(","Y",")",";","b","3",";","r","3","(","Z",")",";","w","1","(","Z",")",";","e","1",";","w","3","(","Z",")",";","e","3",";","e","2",";"]
input_list3=["b","1",";","r","1","(","Y",")",";","r","1","(","Z",")",";","b","2",";","r","2","(","Y",")",";","b","3",";","r","3","(","Y",")",";","w","1","(","Z",")",";","e","1",";","w","2","(","Y",")",";","r","2","(","X",")",";","b","4",";","r","4","(","Z",")",";","r","4","(","Y",")",";","w","2","(","X",")",";","e","2",";","w","4","(","Z",")",";","e","3",";","w","4","(","Y",")",";","e","4",";"]
input_list4=["b","1",";","r","1","(","Y",")",";","w","1","(","Y",")",";","r","1","(","Z",")",";","b","2",";","r","2","(","Y",")",";","b","3",";","r","3","(","Z",")",";","w","3","(","Z",")",";","b","4",";","r","4","(","X",")",";","r","4","(","Y",")",";","e","1",";","w","4","(","X",")",";","e","3",";","e","2",";","w","4","(","Y",")",";","e","4",";"]
tem_operation=[]
transaction_table=[]
lock_table=[]
blocked_queue=[]
#functions
def extend_list(list_one,list_two):#extend the list_two before list_one inside list_one and clear list_two
list_two.extend(list_one)
list_one.clear()
list_one.extend(list_two)
list_two.clear()
def read_an_operation(input_list,tem_operation):
if(len(input_list)==0):#if all operations were done, return False
return False
tem_operation.clear()
while(input_list[0]!=";"):#put an operation into tem_operation and remove from input_list
tem_operation.append(input_list[0])
del input_list[0]
del input_list[0]
tem_operation.append(";")
return True
#because the timestamp is unique and belongs to nature number, we can let the index of the transaction_table be timestamp
def begin_transaction(transaction_id,transaction_table):
tem_class=transaction_class()
tem_class.tid=transaction_id
tem_class.state="active"
transaction_table.append(tem_class)
print("Transaction",transaction_id,"begins.")
def end_transaction(transaction_id,transaction_table,lock_table,blocked_queue,input_list):
i=0
while transaction_table[i].tid!=transaction_id:
i=i+1
if transaction_table[i].state=="aborted":#the transaction has been unlocked,just print
print("Transaction",transaction_table[i].tid,"is already aborted.")
else:
transaction_table[i].state="committed"
print("Transaction",transaction_table[i].tid,"ends.")
unlock(transaction_id,lock_table,blocked_queue)
extend_list(input_list,blocked_queue)#get the new intut list, clear the blocked queue
def abort_transaction(transaction_id,transaction_table,lock_table,blocked_queue):
i=0
while transaction_table[i].tid!=transaction_id:
i=i+1
transaction_table[i].state="aborted"
print("Transaction",transaction_table[i].tid,"is aborted.")
unlock(transaction_id,lock_table,blocked_queue)
def read_lock(transaction_id,item,lock_table,transaction_table,blocked_queue,tem_operation,input_list):
tem_1=0#find the timestamp of the transaction we are using in transaction table
while transaction_table[tem_1].tid!=transaction_id:#check whether the transaction is blocked
tem_1=tem_1+1
if transaction_table[tem_1].state=="aborted":
print("Tansaction",transaction_id,"is already aborted.",tem_operation,"stoped.")
elif transaction_table[tem_1].state=="blocked":
blocked_queue.extend(tem_operation)
print("Transaction",transaction_id,"is already blocked, update blocked queue, current operation stoped.")
else:
tem_class=lock_class()
tem_class.tid.append(transaction_id)
tem_class.item=item
tem_class.mode="read"
tem_class.num_of_reads=1#may be updated later
i=0
while i<len(lock_table):#try to find the item
if(lock_table[i].item==item):
break
i=i+1
if i==len(lock_table):#this item hasn't appeared in the lock table, just add the lock
lock_table.append(tem_class)
print("Item",item,"hasn't appeared in the lock table, current operation success.")
else:#found the item
if lock_table[i].mode=="unlocked":
lock_table[i].tid.append(transaction_id)
lock_table[i].mode="read"
lock_table[i].num_of_reads=1
print("Item",item,"doesn't have a lock, current operation success.")
elif lock_table[i].mode=="read":
lock_table[i].tid.append(transaction_id)
lock_table[i].num_of_reads=lock_table[i].num_of_reads+1
print("Item",item,"has read lock, current operation success.")
else:#the item has write lock
print("Item",item,"has write lock,")
tem_2=0#find the timestamp of the transaction which has the lock in transaction table
while transaction_table[tem_2].tid!=lock_table[i].tid[0]:
tem_2=tem_2+1
if tem_1<tem_2:#wound-wait,wound
abort_transaction(transaction_table[tem_2].tid,transaction_table,lock_table,blocked_queue)
print("abort transaction",transaction_table[tem_2].tid,".")
print("Redo current operation.")
extend_list(input_list,tem_operation)
elif tem_1>tem_2:#wait
blocked_queue.extend(tem_operation)
transaction_table[tem_1].state="blocked"#change the state of the transaction
transaction_table[tem_1].blocked_by=transaction_table[tem_2].tid
print("Current operation waits.")
else:
pass
def write_lock(transaction_id,item,lock_table,transaction_table,blocked_queue,tem_operation,input_list):
tem_1=0
while transaction_table[tem_1].tid!=transaction_id:#check whether the transaction is blocked
tem_1=tem_1+1
if transaction_table[tem_1].state=="aborted":
print("Tansaction",transaction_id,"is already aborted, current operation stoped.")
elif transaction_table[tem_1].state=="blocked":
blocked_queue.extend(tem_operation)
print("Transaction",transaction_id,"is already blocked, update blocked queue, current operation stoped.")
else:
tem_class=lock_class()
tem_class.tid.append(transaction_id)
tem_class.item=item
tem_class.mode="write"
tem_class.num_of_reads=0#may be updated later
i=0
while i<len(lock_table):#try to find the item
if(lock_table[i].item==item):
break
i=i+1
if i==len(lock_table):#this item hasn't appeared in the lock table, just add the lock
lock_table.append(tem_class)
print("Item",item,"hasn't appeared in the lock table, current operation success.")
else:#found the item
if lock_table[i].mode=="unlocked":
lock_table[i].tid.append(transaction_id)
lock_table[i].mode="write"
lock_table[i].num_of_reads=0
print("Item",item,"doesn't have a lock, current operation success.")
elif lock_table[i].mode=="read":
print("Item",item,"has read lock,")
tem_3=0
flag=0#flag for judging whether transactions have been aborted
#print("lock_table[i].tid",lock_table[i].tid)
while tem_3<len(lock_table[i].tid):#walk throuth lock_table[i].tid
tem_2=0#find the timestamp of the transaction which has a lock in transaction table
while transaction_table[tem_2].tid!=lock_table[i].tid[tem_3]:
tem_2=tem_2+1
if tem_1<tem_2:#wound-wait,wound
abort_transaction(transaction_table[tem_2].tid,transaction_table,lock_table,blocked_queue)
flag=1
tem_3=tem_3+1
if flag==1:#transactions have been aborted
print("Redo current operation.")
extend_list(input_list,tem_operation)
else:#no younger lock,only older or itself
tem_4=0
while tem_4<len(lock_table[i].tid):
tem_5=0#find the timestamp of the transaction which has a lock in transaction table
while transaction_table[tem_5].tid!=lock_table[i].tid[tem_4]:
tem_5=tem_5+1
if tem_1>tem_5:#found an older block
break
tem_4=tem_4+1
if tem_4!=len(lock_table[i].tid):#wait
blocked_queue.extend(tem_operation)
transaction_table[tem_1].state="blocked"#change the state of the transaction
transaction_table[tem_1].blocked_by=transaction_table[tem_4].tid
print("Current operation waits.")
else:#upgrade
lock_table[i].mode="write"
lock_table[i].num_of_reads=0
print("Current operation upgrade.")
else:#the item has write lock
print("Item",item,"has write lock,")
tem_2=0#find the timestamp of the transaction which has the lock in transaction table
while transaction_table[tem_2].tid!=lock_table[i].tid[0]:
tem_2=tem_2+1
if tem_1<tem_2:#wound-wait,wound
abort_transaction(transaction_table[tem_2].tid,transaction_table,lock_table)
print("Abort transaction",transaction_table[tem_2].tid,".")
print("Redo current operation.")
extend_list(input_list,tem_operation)
elif tem_1>tem_2:#wait
blocked_queue.extend(tem_operation)
transaction_table[tem_1].state="blocked"#change the state of the transaction
transaction_table[tem_1].blocked_by=transaction_table[tem2].tid
print("Current operation waits.")
else:
pass
def unlock(transaction_id,lock_table,blocked_queue):
#update lock_table
i=0
while i<len(lock_table):#walk through lock_table
j=0
while j<len(lock_table[i].tid):#walk through lock_table[i].tid
if lock_table[i].tid[j]==transaction_id:
if lock_table[i].mode=="write":
lock_table[i].mode="unlocked"
lock_table[i].num_of_reads=0
elif lock_table[i].mode=="read":
lock_table[i].num_of_reads=lock_table[i].num_of_reads-1
if lock_table[i].num_of_reads==0:
lock_table[i].mode="unlocked"
else:
pass
del lock_table[i].tid[j]
break
else:
j=j+1
i=i+1
#update transaction_table
i=0
while i<len(transaction_table):
if transaction_table[i].blocked_by==transaction_id and transaction_table[i].state!="aborted":
transaction_table[i].state="active"
transaction_table[i].blocked_by=""
i=i+1
#update blocked_queue
tem_len=len(blocked_queue)#this length will change all the time,save it
tem_1=0
tem_2=0
k=0
while tem_2<tem_len:#delete all the operations of the unlocked transaction,notice that only read and write can be blocded
if blocked_queue[tem_1+1]==transaction_id:
k=0
while k<6:#6 is the length of one operation
del blocked_queue[tem_1]
k=k+1
else:
tem_1=tem_1+6
tem_2=tem_2+6
def clear_list(tem_operation,transaction_table,lock_table,blocked_queue):
tem_operation.clear()
transaction_table.clear()
lock_table.clear()
blocked_queue.clear()
def print_current_operation(tem_operation):
tem_counter=0
while(tem_operation[tem_counter]!=";"):
print(tem_operation[tem_counter],end="")
tem_counter=tem_counter+1
print(tem_operation[tem_counter],end="")
#main program
print("********************The first input begins.********************")
while read_an_operation(input_list,tem_operation):
print_current_operation(tem_operation)
print()
if tem_operation[0]=="b":#assume that one transaction only begins one time
begin_transaction(tem_operation[1],transaction_table)
elif tem_operation[0]=="r":
read_lock(tem_operation[1],tem_operation[3],lock_table,transaction_table,blocked_queue,tem_operation,input_list)
elif tem_operation[0]=="w":
write_lock(tem_operation[1],tem_operation[3],lock_table,transaction_table,blocked_queue,tem_operation,input_list)
else:#assume that one transaction only ends one time
end_transaction(tem_operation[1],transaction_table,lock_table,blocked_queue,input_list)
print()
print("********************The first input is finished.********************")
clear_list(tem_operation,transaction_table,lock_table,blocked_queue)
print()
print("********************The second input begins.********************")
while read_an_operation(input_list2,tem_operation):
print_current_operation(tem_operation)
print()
if tem_operation[0]=="b":#assume that one transaction only begins one time
begin_transaction(tem_operation[1],transaction_table)
elif tem_operation[0]=="r":
read_lock(tem_operation[1],tem_operation[3],lock_table,transaction_table,blocked_queue,tem_operation,input_list2)
elif tem_operation[0]=="w":
write_lock(tem_operation[1],tem_operation[3],lock_table,transaction_table,blocked_queue,tem_operation,input_list2)
else:#assume that one transaction only ends one time
end_transaction(tem_operation[1],transaction_table,lock_table,blocked_queue,input_list2)
print()
print("********************The second input is finished.********************")
clear_list(tem_operation,transaction_table,lock_table,blocked_queue)
print()
print("********************The third input begins.********************")
while read_an_operation(input_list3,tem_operation):
print_current_operation(tem_operation)
print()
if tem_operation[0]=="b":#assume that one transaction only begins one time
begin_transaction(tem_operation[1],transaction_table)
elif tem_operation[0]=="r":
read_lock(tem_operation[1],tem_operation[3],lock_table,transaction_table,blocked_queue,tem_operation,input_list3)
elif tem_operation[0]=="w":
write_lock(tem_operation[1],tem_operation[3],lock_table,transaction_table,blocked_queue,tem_operation,input_list3)
else:#assume that one transaction only ends one time
end_transaction(tem_operation[1],transaction_table,lock_table,blocked_queue,input_list3)
print()
print("********************The third input is finished.********************")
clear_list(tem_operation,transaction_table,lock_table,blocked_queue)
print()
print("********************The last input begins.********************")
while read_an_operation(input_list4,tem_operation):
print_current_operation(tem_operation)
print()
if tem_operation[0]=="b":#assume that one transaction only begins one time
begin_transaction(tem_operation[1],transaction_table)
elif tem_operation[0]=="r":
read_lock(tem_operation[1],tem_operation[3],lock_table,transaction_table,blocked_queue,tem_operation,input_list4)
elif tem_operation[0]=="w":
write_lock(tem_operation[1],tem_operation[3],lock_table,transaction_table,blocked_queue,tem_operation,input_list4)
else:#assume that one transaction only ends one time
end_transaction(tem_operation[1],transaction_table,lock_table,blocked_queue,input_list4)
print()
print("********************The last input is finished.********************")
clear_list(tem_operation,transaction_table,lock_table,blocked_queue)
print()