使用wound-wait处理死锁的两段锁(2pl)模拟代码

背景

这是数据库大作业。本来过了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()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值