Skip to content
This repository has been archived by the owner on Feb 4, 2020. It is now read-only.

Commit

Permalink
Merge pull request #296 from siu/atomicCacheEntryWrites
Browse files Browse the repository at this point in the history
Replace whole cache entries atomically
  • Loading branch information
frerich committed Oct 13, 2017
2 parents 24ecf96 + 26f01f0 commit 30ac5b9
Showing 1 changed file with 34 additions and 21 deletions.
55 changes: 34 additions & 21 deletions clcache.py
Expand Up @@ -124,6 +124,17 @@ def atomicWrite(fileName):
os.replace(tempFileName, fileName)


def getCachedCompilerConsoleOutput(path):
try:
with open(path, 'rb') as f:
return f.read().decode(CACHE_COMPILER_OUTPUT_STORAGE_CODEC)
except IOError:
return ''

def setCachedCompilerConsoleOutput(path, output):
with open(path, 'wb') as f:
f.write(output.encode(CACHE_COMPILER_OUTPUT_STORAGE_CODEC))

class IncludeNotFoundException(Exception):
pass

Expand Down Expand Up @@ -354,6 +365,10 @@ def forPath(path):


class CompilerArtifactsSection(object):
OBJECT_FILE = 'object'
STDOUT_FILE = 'output.txt'
STDERR_FILE = 'stderr.txt'

def __init__(self, compilerArtifactsSectionDir):
self.compilerArtifactsSectionDir = compilerArtifactsSectionDir
self.lock = CacheLock.forPath(self.compilerArtifactsSectionDir)
Expand All @@ -365,40 +380,38 @@ def cacheEntries(self):
return childDirectories(self.compilerArtifactsSectionDir, absolute=False)

def cachedObjectName(self, key):
return os.path.join(self.cacheEntryDir(key), "object")
return os.path.join(self.cacheEntryDir(key), CompilerArtifactsSection.OBJECT_FILE)

def hasEntry(self, key):
return os.path.exists(self.cacheEntryDir(key))

def setEntry(self, key, artifacts):
ensureDirectoryExists(self.cacheEntryDir(key))
cacheEntryDir = self.cacheEntryDir(key)
# Write new files to a temporary directory
tempEntryDir = cacheEntryDir + '.new'
# Remove any possible left-over in tempEntryDir from previous executions
rmtree(tempEntryDir, ignore_errors=True)
ensureDirectoryExists(tempEntryDir)
if artifacts.objectFilePath is not None:
copyOrLink(artifacts.objectFilePath, self.cachedObjectName(key))
self._setCachedCompilerConsoleOutput(key, 'output.txt', artifacts.stdout)
copyOrLink(artifacts.objectFilePath,
os.path.join(tempEntryDir, CompilerArtifactsSection.OBJECT_FILE))
setCachedCompilerConsoleOutput(os.path.join(tempEntryDir, CompilerArtifactsSection.STDOUT_FILE),
artifacts.stdout)
if artifacts.stderr != '':
self._setCachedCompilerConsoleOutput(key, 'stderr.txt', artifacts.stderr)
setCachedCompilerConsoleOutput(os.path.join(tempEntryDir, CompilerArtifactsSection.STDERR_FILE),
artifacts.stderr)
# Replace the full cache entry atomically
os.replace(tempEntryDir, cacheEntryDir)

def getEntry(self, key):
assert self.hasEntry(key)
cacheEntryDir = self.cacheEntryDir(key)
return CompilerArtifacts(
self.cachedObjectName(key),
self._getCachedCompilerConsoleOutput(key, 'output.txt'),
self._getCachedCompilerConsoleOutput(key, 'stderr.txt')
os.path.join(cacheEntryDir, CompilerArtifactsSection.OBJECT_FILE),
getCachedCompilerConsoleOutput(os.path.join(cacheEntryDir, CompilerArtifactsSection.STDOUT_FILE)),
getCachedCompilerConsoleOutput(os.path.join(cacheEntryDir, CompilerArtifactsSection.STDERR_FILE))
)

def _getCachedCompilerConsoleOutput(self, key, fileName):
try:
outputFilePath = os.path.join(self.cacheEntryDir(key), fileName)
with open(outputFilePath, 'rb') as f:
return f.read().decode(CACHE_COMPILER_OUTPUT_STORAGE_CODEC)
except IOError:
return ''

def _setCachedCompilerConsoleOutput(self, key, fileName, output):
outputFilePath = os.path.join(self.cacheEntryDir(key), fileName)
with open(outputFilePath, 'wb') as f:
f.write(output.encode(CACHE_COMPILER_OUTPUT_STORAGE_CODEC))


class CompilerArtifactsRepository(object):
def __init__(self, compilerArtifactsRootDir):
Expand Down

0 comments on commit 30ac5b9

Please sign in to comment.