Timestamp Approach
code
import random, simpy
RUNTIME = 1 #simulation times
DATA_BLOCK = 30
INTERVAL = 3 #the maximum interval of adjacent two operations is 3
MAXTIME = 5 #the maximum execution time of a single operation is 5
SIM_TIME = 1000
processQueue = [] #the process waiting queue, set max size 4
global writeNum
global invalidWrite
writeNum = 0
invalidWrite = 0
datablocks = []
class DataBlock(object):
def __init__(self, id, lock_mode, readersNum,timestamp):
self.id = id
self.lock_mode = lock_mode
self.readersNum = readersNum
self.timestamp = timestamp
class Operation(object):
def __init__(self,maxtime):
self.maxtime = maxtime
#self.env = env
def read(self, env, name, datablock): #read operation method
print("%s is reading datablock No.%s at %s" %(name,datablock.id,env.now))
operateTime = random.randint(1,MAXTIME)
datablock.timestamp = env.now + operateTime #update corresponding datablock's timestamp to the time the read operation would stop
yield env.timeout(operateTime)
print("%s has finished reading datablock No.%s at %s" %(name,datablock.id,env.now))
processQueue.remove(name)
def write(self, env, name, datablock): #write operation method
global writeNum
global invalidWrite
writeNum = writeNum+1 #increment writenum
if datablock.timestamp > env.now: #last operation of this datablock has not ended yet, it is a invalid dirty write operation, reattempt
invalidWrite = invalidWrite + 1 #increment the number of invalidWrite
print('Operation %s is an invalid dirty write on datablock %d at time %.2f, reattempted.' % (name, datablock.id, env.now))
#while datablock.timestamp > env.now:
# yield env.timeout(1)
curTime = env.now
while datablock.timestamp > curTime:
curTime = curTime + 1
#wait last operation end
operateTime = random.randint(1,MAXTIME)
datablock.timestamp = env.now + operateTime
print("%s is writing datablock No.%s at %s" %(name,datablock.id,env.now))
yield env.timeout(operateTime)
print("%s has finished writing datablock No.%s at %s" %(name,datablock.id,env.now))
def setup(env, maxtime, interval, datablocks):
operation = Operation(maxtime)
i = 0
while True:
yield env.timeout(random.randint(0,interval)) #stop for next operation
blockNum = random.randint(0,DATA_BLOCK-1) #generate block number randomly
mode = "";
if random.random()<0.25: #according possibility to specify the mode
mode = "W"
else:
mode = "R"
if len(processQueue) == 4: #if the queue is full, wait
yield env.timeout(maxtime*3)
processQueue.append('Operation %d' %i) #push current operate into the queue
print('the blockNum is %d' %blockNum)
db = datablocks[blockNum] #get corresponding datablock object
if mode == "R": #execute corresponding operation
env.process(operation.read(env,'Operation %d' % i,db))
else:
env.process(operation.write(env,'Operation %d' % i,db))
i = i+1
for i in range(DATA_BLOCK): #initialize datablocks
datablocks.append(DataBlock(i, '', 0,0))
env = simpy.Environment()
env.process(setup(env, MAXTIME, INTERVAL,datablocks))
i = 0
while i < RUNTIME:
env.run(until=SIM_TIME)
SIM_TIME += 10000
i = i + 1
percent = (invalidWrite/writeNum)*100
print('When we run %d times, total write number: %d, invalid write number: %d. The percent of invalid write is %.3f %%.' %(RUNTIME,writeNum,invalidWrite,percent))