- Split cache again out of test program.

This commit is contained in:
ccremers 2005-03-04 15:34:41 +00:00
parent 614b3441ad
commit 21c3f19f66
2 changed files with 143 additions and 129 deletions

View File

@ -1,138 +1,12 @@
#!/usr/bin/python #!/usr/bin/python
# #
# Scyther caching mechanism # Scyther wrapper
# #
# Uses md5 hashes to store previously calculated results. # Standard tests
# #
# (c)2005 Cas Cremers
#
#
# TODO:
#
# - Maybe it is an idea to time the output. If Scyther takes less
# than a second, we don't need to cache the output. That would
# reduce the required cache size significantly.
# If so, we only need to create directories for the cached files
# we actually create.
#
import md5
import commands
import os
import sys import sys
import time
from tempfile import NamedTemporaryFile, gettempdir
from optparse import OptionParser from optparse import OptionParser
from scythercache import evaluate
#----------------------------------------------------------------------------
# Global definitions
#----------------------------------------------------------------------------
# Minimum duration for something to get into the cache
CacheTimer = 0.1
#----------------------------------------------------------------------------
# How to call Scyther
#----------------------------------------------------------------------------
# scyther should reside in $PATH
def scythercall (argumentstring, inputfile):
clstring = "scyther " + argumentstring + " " + inputfile
(status,scout) = commands.getstatusoutput(clstring)
return (status,scout)
#----------------------------------------------------------------------------
# Cached evaluation
#----------------------------------------------------------------------------
# cached results
# input: a large string (consisting of read input files)
# argstring: a smaller string
def evaluate (argumentstring, inputstring):
def cacheid():
m = md5.new()
# # Determine scyther version
# (status, scout) = scythercall ("--version", "")
# if status == 1 or status < 0:
# # some problem
# print "Problem with determining scyther version!"
# os.exit()
# # Add version to hash
# m.update (scout)
# Add inputfile to hash
m.update (inputstring)
# Add arguments to hash
m.update (argumentstring)
# Return a readable ID (good for a filename)
return m.hexdigest()
# slashcutter
# Takes 'str': cuts of the first 'depth' strings of length
# 'width' and puts 'substr' in between
def slashcutter(str,substr,width,depth):
res = ""
while len(str)>width and depth>0:
res = res + str[0:width] + substr
str = str[width:]
depth = depth-1
return res + str
# Determine name
def cachefilename(id):
fn = gettempdir() + "/scyther/"
fn = fn + slashcutter(id,"/",3,2)
fn = fn + ".txt"
return fn
# Ensure directory
def ensureDirectory (path):
if not os.path.exists(path):
os.mkdir(path)
# Ensure directories for a file
def ensureDirectories (filename):
for i in range(1,len(filename)):
if filename[i] == '/':
np = i+1
ensureDirectory(filename[:np])
# Determine the unique filename for this test
cachefile = cachefilename(cacheid())
# Does it already exist?
if os.path.exists(cachefile):
# Great: return the cached results
f = open(cachefile,'r')
res = f.read()
f.close()
# TODO technically, we should store the status in the
# cache file as well. For now, we just return 0 status.
return (0,res)
else:
# Hmm, we need to compute this result
# Compute duration (in seconds)
h = NamedTemporaryFile()
h.write(inputstring)
h.flush()
starttime = time.time()
(status, scout) = scythercall (argumentstring, h.name)
duration = time.time() - starttime
h.close()
# Only cache if it took some time
if duration >= CacheTimer:
# Write cache file even if it's wrong
ensureDirectories(cachefile)
f = open(cachefile,'w')
f.write(scout)
f.close()
return (status,scout)
#---------------------------------------------------------------------------- #----------------------------------------------------------------------------
# Parsing Output # Parsing Output

140
test/scythercache.py Executable file
View File

@ -0,0 +1,140 @@
#!/usr/bin/python
#
# Scyther caching mechanism
#
# Uses md5 hashes to store previously calculated results.
#
# (c)2005 Cas Cremers
#
#
import md5
import commands
import os
import sys
import time
from tempfile import NamedTemporaryFile, gettempdir
#----------------------------------------------------------------------------
# Global definitions
#----------------------------------------------------------------------------
# Minimum duration for a test to get into the cache (in seconds)
CacheTimer = 0.1
#----------------------------------------------------------------------------
# How to call Scyther
#----------------------------------------------------------------------------
# scyther should reside in $PATH
def scythercall (argumentstring, inputfile):
clstring = "scyther " + argumentstring + " " + inputfile
(status,scout) = commands.getstatusoutput(clstring)
return (status,scout)
#----------------------------------------------------------------------------
# Cached evaluation
#----------------------------------------------------------------------------
# cached results
# input: a large string (consisting of read input files)
# argstring: a smaller string
def evaluate (argumentstring, inputstring):
def cacheid():
m = md5.new()
# # Determine scyther version
# (status, scout) = scythercall ("--version", "")
# if status == 1 or status < 0:
# # some problem
# print "Problem with determining scyther version!"
# os.exit()
# # Add version to hash
# m.update (scout)
# Add inputfile to hash
m.update (inputstring)
# Add arguments to hash
m.update (argumentstring)
# Return a readable ID (good for a filename)
return m.hexdigest()
# slashcutter
# Takes 'str': cuts of the first 'depth' strings of length
# 'width' and puts 'substr' in between
def slashcutter(str,substr,width,depth):
res = ""
while len(str)>width and depth>0:
res = res + str[0:width] + substr
str = str[width:]
depth = depth-1
return res + str
# Determine name
def cachefilename(id):
fn = gettempdir() + "/scyther/"
fn = fn + slashcutter(id,"/",3,2)
fn = fn + ".txt"
return fn
# Ensure directory
def ensureDirectory (path):
if not os.path.exists(path):
os.mkdir(path)
# Ensure directories for a file
def ensureDirectories (filename):
for i in range(1,len(filename)):
if filename[i] == '/':
np = i+1
ensureDirectory(filename[:np])
def compute_and_cache(cachefile):
# Hmm, we need to compute this result
# Compute duration (in seconds)
h = NamedTemporaryFile()
h.write(inputstring)
h.flush()
starttime = time.time()
(status, scout) = scythercall (argumentstring, h.name)
duration = time.time() - starttime
h.close()
# Only cache if it took some time
if duration >= CacheTimer:
# Write cache file even if it's wrong
ensureDirectories(cachefile)
f = open(cachefile,'w')
f.write(scout)
f.close()
return (status,scout)
def retrieve_from_cache(file):
f = open(file,'r')
res = f.read()
f.close()
# TODO technically, we should store the status in the
# cache file as well. For now, we just return 0 status.
return (0,res)
# Determine the unique filename for this test
cachefile = cachefilename(cacheid())
if os.path.exists(cachefile):
return retrieve_from_cache(cachefile)
else:
return compute_and_cache(cachefile)
#----------------------------------------------------------------------------
# Standalone usage
#----------------------------------------------------------------------------
def main():
print "This module has currently no standalone functionality."
# Only if main stuff
if __name__ == '__main__':
main()