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

Commit 30ac5b9

Browse files
authored
Merge pull request #296 from siu/atomicCacheEntryWrites
Replace whole cache entries atomically
2 parents 24ecf96 + 26f01f0 commit 30ac5b9

1 file changed

Lines changed: 34 additions & 21 deletions

File tree

clcache.py

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,17 @@ def atomicWrite(fileName):
124124
os.replace(tempFileName, fileName)
125125

126126

127+
def getCachedCompilerConsoleOutput(path):
128+
try:
129+
with open(path, 'rb') as f:
130+
return f.read().decode(CACHE_COMPILER_OUTPUT_STORAGE_CODEC)
131+
except IOError:
132+
return ''
133+
134+
def setCachedCompilerConsoleOutput(path, output):
135+
with open(path, 'wb') as f:
136+
f.write(output.encode(CACHE_COMPILER_OUTPUT_STORAGE_CODEC))
137+
127138
class IncludeNotFoundException(Exception):
128139
pass
129140

@@ -354,6 +365,10 @@ def forPath(path):
354365

355366

356367
class CompilerArtifactsSection(object):
368+
OBJECT_FILE = 'object'
369+
STDOUT_FILE = 'output.txt'
370+
STDERR_FILE = 'stderr.txt'
371+
357372
def __init__(self, compilerArtifactsSectionDir):
358373
self.compilerArtifactsSectionDir = compilerArtifactsSectionDir
359374
self.lock = CacheLock.forPath(self.compilerArtifactsSectionDir)
@@ -365,40 +380,38 @@ def cacheEntries(self):
365380
return childDirectories(self.compilerArtifactsSectionDir, absolute=False)
366381

367382
def cachedObjectName(self, key):
368-
return os.path.join(self.cacheEntryDir(key), "object")
383+
return os.path.join(self.cacheEntryDir(key), CompilerArtifactsSection.OBJECT_FILE)
369384

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

373388
def setEntry(self, key, artifacts):
374-
ensureDirectoryExists(self.cacheEntryDir(key))
389+
cacheEntryDir = self.cacheEntryDir(key)
390+
# Write new files to a temporary directory
391+
tempEntryDir = cacheEntryDir + '.new'
392+
# Remove any possible left-over in tempEntryDir from previous executions
393+
rmtree(tempEntryDir, ignore_errors=True)
394+
ensureDirectoryExists(tempEntryDir)
375395
if artifacts.objectFilePath is not None:
376-
copyOrLink(artifacts.objectFilePath, self.cachedObjectName(key))
377-
self._setCachedCompilerConsoleOutput(key, 'output.txt', artifacts.stdout)
396+
copyOrLink(artifacts.objectFilePath,
397+
os.path.join(tempEntryDir, CompilerArtifactsSection.OBJECT_FILE))
398+
setCachedCompilerConsoleOutput(os.path.join(tempEntryDir, CompilerArtifactsSection.STDOUT_FILE),
399+
artifacts.stdout)
378400
if artifacts.stderr != '':
379-
self._setCachedCompilerConsoleOutput(key, 'stderr.txt', artifacts.stderr)
401+
setCachedCompilerConsoleOutput(os.path.join(tempEntryDir, CompilerArtifactsSection.STDERR_FILE),
402+
artifacts.stderr)
403+
# Replace the full cache entry atomically
404+
os.replace(tempEntryDir, cacheEntryDir)
380405

381406
def getEntry(self, key):
382407
assert self.hasEntry(key)
408+
cacheEntryDir = self.cacheEntryDir(key)
383409
return CompilerArtifacts(
384-
self.cachedObjectName(key),
385-
self._getCachedCompilerConsoleOutput(key, 'output.txt'),
386-
self._getCachedCompilerConsoleOutput(key, 'stderr.txt')
410+
os.path.join(cacheEntryDir, CompilerArtifactsSection.OBJECT_FILE),
411+
getCachedCompilerConsoleOutput(os.path.join(cacheEntryDir, CompilerArtifactsSection.STDOUT_FILE)),
412+
getCachedCompilerConsoleOutput(os.path.join(cacheEntryDir, CompilerArtifactsSection.STDERR_FILE))
387413
)
388414

389-
def _getCachedCompilerConsoleOutput(self, key, fileName):
390-
try:
391-
outputFilePath = os.path.join(self.cacheEntryDir(key), fileName)
392-
with open(outputFilePath, 'rb') as f:
393-
return f.read().decode(CACHE_COMPILER_OUTPUT_STORAGE_CODEC)
394-
except IOError:
395-
return ''
396-
397-
def _setCachedCompilerConsoleOutput(self, key, fileName, output):
398-
outputFilePath = os.path.join(self.cacheEntryDir(key), fileName)
399-
with open(outputFilePath, 'wb') as f:
400-
f.write(output.encode(CACHE_COMPILER_OUTPUT_STORAGE_CODEC))
401-
402415

403416
class CompilerArtifactsRepository(object):
404417
def __init__(self, compilerArtifactsRootDir):

0 commit comments

Comments
 (0)