Skip to content

Commit abe10f0

Browse files
authored
Merge pull request #2 from izmmisha/add-tracker-support
Add tracker support
2 parents 7a3e62a + d78537f commit abe10f0

File tree

9 files changed

+216
-31
lines changed

9 files changed

+216
-31
lines changed

appveyor.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ environment:
88
# AppVeyor installed Python versions
99
# http://www.appveyor.com/docs/installed-software#python
1010

11-
- PYTHON_INSTALL: "C:\\Python34"
1211
- PYTHON_INSTALL: "C:\\Python35"
1312
- PYTHON_INSTALL: "C:\\Python36"
1413

@@ -27,16 +26,16 @@ install:
2726
- set PATH=%PYTHON_INSTALL%;%PATH%
2827

2928
# Prepend Python scripts to PATH (e.g. pip, py.test, pylint)
30-
- set PATH=%PYTHON_INSTALL%\\Scripts;%PATH%
29+
- set PATH=%PYTHON_INSTALL%\Scripts;%PATH%
3130

31+
- echo "PATH is %PATH%"
3232
# Check Python version
3333
- python --version
3434

3535
# Upgrade the Python build tools
36-
- pip install -U pip setuptools wheel
36+
- python -m pip install --upgrade pip setuptools wheel
3737

3838
# Check pip version
39-
- python -m pip install --upgrade pip setuptools wheel
4039
- pip --version
4140

4241
# Install pytest
@@ -56,7 +55,8 @@ install:
5655
- pip install .
5756

5857
# Install tool for uploading coverage data to codecov.io
59-
- pip install codecov
58+
- choco install codecov
59+
- where coverage
6060
- coverage --version
6161

6262
# Install dependencies for clcachesrv such that we can lint the source code
@@ -96,7 +96,7 @@ test_script:
9696
$wc = New-Object 'System.Net.WebClient'
9797
$wc.UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\unittests.xml))
9898
99-
& codecov --no-color -X gcov -F unittests -e PYTHON_INSTALL
99+
& codecov -f coverage.xml
100100
101101
if ($testsExitCode -ne 0) {exit $testsExitCode}
102102
@@ -113,7 +113,7 @@ test_script:
113113
$wc = New-Object 'System.Net.WebClient'
114114
$wc.UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\integrationtests.xml))
115115
116-
& codecov --no-color -X gcov -F integrationtests_memcached -e PYTHON_INSTALL
116+
& codecov -f coverage.xml
117117
118118
if ($testsExitCode -ne 0) {exit $testsExitCode}
119119

clcache/__main__.py

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
except ImportError:
4343
WALK = os.walk
4444
try:
45-
LIST = os.scandir # pylint: disable=no-name-in-module
45+
LIST = os.scandir # type: ignore # pylint: disable=no-name-in-module
4646
except AttributeError:
4747
LIST = os.listdir
4848

@@ -94,7 +94,7 @@ def filesBeneath(baseDir):
9494

9595

9696
def childDirectories(path, absolute=True):
97-
supportsScandir = (LIST != os.listdir)
97+
supportsScandir = (LIST != os.listdir) # pylint: disable=comparison-with-callable
9898
for entry in LIST(path):
9999
if supportsScandir:
100100
if entry.is_dir():
@@ -116,6 +116,44 @@ def normalizeBaseDir(baseDir):
116116
return None
117117

118118

119+
class SuspendTracker():
120+
fileTracker = None
121+
def __init__(self):
122+
if not SuspendTracker.fileTracker:
123+
if windll.kernel32.GetModuleHandleW("FileTracker.dll"):
124+
SuspendTracker.fileTracker = windll.FileTracker
125+
elif windll.kernel32.GetModuleHandleW("FileTracker32.dll"):
126+
SuspendTracker.fileTracker = windll.FileTracker32
127+
128+
def __enter__(self):
129+
SuspendTracker.suspend()
130+
131+
def __exit__(self, typ, value, traceback):
132+
SuspendTracker.resume()
133+
134+
@staticmethod
135+
def suspend():
136+
if SuspendTracker.fileTracker:
137+
SuspendTracker.fileTracker.SuspendTracking()
138+
139+
@staticmethod
140+
def resume():
141+
if SuspendTracker.fileTracker:
142+
SuspendTracker.fileTracker.ResumeTracking()
143+
144+
def isTrackerEnabled():
145+
return 'TRACKER_ENABLED' in os.environ
146+
147+
def untrackable(func):
148+
if not isTrackerEnabled():
149+
return func
150+
151+
def untrackedFunc(*args, **kwargs):
152+
with SuspendTracker():
153+
return func(*args, **kwargs)
154+
155+
return untrackedFunc
156+
119157
@contextlib.contextmanager
120158
def atomicWrite(fileName):
121159
tempFileName = fileName + '.new'
@@ -163,7 +201,7 @@ def __str__(self):
163201
return repr(self.message)
164202

165203

166-
class Manifest(object):
204+
class Manifest:
167205
def __init__(self, entries=None):
168206
if entries is None:
169207
entries = []
@@ -182,7 +220,7 @@ def touchEntry(self, objectHash):
182220
self._entries.insert(0, self._entries.pop(entryIndex))
183221

184222

185-
class ManifestSection(object):
223+
class ManifestSection:
186224
def __init__(self, manifestSectionDir):
187225
self.manifestSectionDir = manifestSectionDir
188226
self.lock = CacheLock.forPath(self.manifestSectionDir)
@@ -193,6 +231,7 @@ def manifestPath(self, manifestHash):
193231
def manifestFiles(self):
194232
return filesBeneath(self.manifestSectionDir)
195233

234+
@untrackable
196235
def setManifest(self, manifestHash, manifest):
197236
manifestPath = self.manifestPath(manifestHash)
198237
printTraceStatement("Writing manifest with manifestHash = {} to {}".format(manifestHash, manifestPath))
@@ -203,6 +242,7 @@ def setManifest(self, manifestHash, manifest):
203242
jsonobject = {'entries': entries}
204243
json.dump(jsonobject, outFile, sort_keys=True, indent=2)
205244

245+
@untrackable
206246
def getManifest(self, manifestHash):
207247
fileName = self.manifestPath(manifestHash)
208248
if not os.path.exists(fileName):
@@ -231,7 +271,7 @@ def allSectionsLocked(repository):
231271
section.lock.release()
232272

233273

234-
class ManifestRepository(object):
274+
class ManifestRepository:
235275
# Bump this counter whenever the current manifest file format changes.
236276
# E.g. changing the file format from {'oldkey': ...} to {'newkey': ...} requires
237277
# invalidation, such that a manifest that was stored using the old format is not
@@ -308,7 +348,7 @@ def getIncludesContentHashForHashes(listOfHashes):
308348
return HashAlgorithm(','.join(listOfHashes).encode()).hexdigest()
309349

310350

311-
class CacheLock(object):
351+
class CacheLock:
312352
""" Implements a lock for the object cache which
313353
can be used in 'with' statements. """
314354
INFINITE = 0xFFFFFFFF
@@ -364,7 +404,7 @@ def forPath(path):
364404
return CacheLock(lockName, timeoutMs)
365405

366406

367-
class CompilerArtifactsSection(object):
407+
class CompilerArtifactsSection:
368408
OBJECT_FILE = 'object'
369409
STDOUT_FILE = 'output.txt'
370410
STDERR_FILE = 'stderr.txt'
@@ -413,7 +453,7 @@ def getEntry(self, key):
413453
)
414454

415455

416-
class CompilerArtifactsRepository(object):
456+
class CompilerArtifactsRepository:
417457
def __init__(self, compilerArtifactsRootDir):
418458
self._compilerArtifactsRootDir = compilerArtifactsRootDir
419459

@@ -501,7 +541,7 @@ def _normalizedCommandLine(cmdline):
501541
return [arg for arg in cmdline
502542
if not (arg[0] in "/-" and arg[1:].startswith(argsToStrip))]
503543

504-
class CacheFileStrategy(object):
544+
class CacheFileStrategy:
505545
def __init__(self, cacheDirectory=None):
506546
self.dir = cacheDirectory
507547
if not self.dir:
@@ -591,7 +631,7 @@ def clean(self, stats, maximumSize):
591631
stats.setNumCacheEntries(currentCompilerArtifactsCount)
592632

593633

594-
class Cache(object):
634+
class Cache:
595635
def __init__(self, cacheDirectory=None):
596636
if os.environ.get("CLCACHE_MEMCACHED"):
597637
from .storage import CacheFileWithMemcacheFallbackStrategy
@@ -644,7 +684,7 @@ def getManifest(self, manifestHash):
644684
return self.strategy.getManifest(manifestHash)
645685

646686

647-
class PersistentJSONDict(object):
687+
class PersistentJSONDict:
648688
def __init__(self, fileName):
649689
self._dirty = False
650690
self._dict = {}
@@ -676,7 +716,7 @@ def __eq__(self, other):
676716
return type(self) is type(other) and self.__dict__ == other.__dict__
677717

678718

679-
class Configuration(object):
719+
class Configuration:
680720
_defaultValues = {"MaximumCacheSize": 1073741824} # 1 GiB
681721

682722
def __init__(self, configurationFile):
@@ -701,7 +741,7 @@ def setMaximumCacheSize(self, size):
701741
self._cfg["MaximumCacheSize"] = size
702742

703743

704-
class Statistics(object):
744+
class Statistics:
705745
CALLS_WITH_INVALID_ARGUMENT = "CallsWithInvalidArgument"
706746
CALLS_WITHOUT_SOURCE_FILE = "CallsWithoutSourceFile"
707747
CALLS_WITH_MULTIPLE_SOURCE_FILES = "CallsWithMultipleSourceFiles"
@@ -741,13 +781,15 @@ def __init__(self, statsFile):
741781
self._stats = None
742782
self.lock = CacheLock.forPath(self._statsFile)
743783

784+
@untrackable
744785
def __enter__(self):
745786
self._stats = PersistentJSONDict(self._statsFile)
746787
for k in Statistics.RESETTABLE_KEYS | Statistics.NON_RESETTABLE_KEYS:
747788
if k not in self._stats:
748789
self._stats[k] = 0
749790
return self
750791

792+
@untrackable
751793
def __exit__(self, typ, value, traceback):
752794
# Does not write to disc when unchanged
753795
self._stats.save()
@@ -1026,7 +1068,7 @@ def printTraceStatement(msg: str) -> None:
10261068
print(os.path.join(scriptDir, "clcache.py") + " " + msg)
10271069

10281070

1029-
class CommandLineTokenizer(object):
1071+
class CommandLineTokenizer:
10301072
def __init__(self, content):
10311073
self.argv = []
10321074
self._content = content
@@ -1154,7 +1196,7 @@ def extendCommandLineFromEnvironment(cmdLine, environment):
11541196
return cmdLine, remainingEnvironment
11551197

11561198

1157-
class Argument(object):
1199+
class Argument:
11581200
def __init__(self, name):
11591201
self.name = name
11601202

@@ -1192,7 +1234,7 @@ class ArgumentT4(Argument):
11921234
pass
11931235

11941236

1195-
class CommandLineAnalyzer(object):
1237+
class CommandLineAnalyzer:
11961238

11971239
@staticmethod
11981240
def _getParameterizedArgumentType(cmdLineArgument):
@@ -1645,7 +1687,13 @@ def scheduleJobs(cache: Any, compiler: str, cmdLine: List[str], environment: Any
16451687

16461688
exitCode = 0
16471689
cleanupRequired = False
1648-
with concurrent.futures.ThreadPoolExecutor(max_workers=jobCount(cmdLine)) as executor:
1690+
1691+
def poolExecutor(*args, **kwargs) -> concurrent.futures.Executor:
1692+
if isTrackerEnabled():
1693+
return concurrent.futures.ProcessPoolExecutor(*args, **kwargs)
1694+
return concurrent.futures.ThreadPoolExecutor(*args, **kwargs)
1695+
1696+
with poolExecutor(max_workers=min(jobCount(cmdLine), len(objectFiles))) as executor:
16491697
jobs = []
16501698
for (srcFile, srcLanguage), objFile in zip(sourceFiles, objectFiles):
16511699
jobCmdLine = baseCmdLine + [srcLanguage + srcFile]

clcache/server/__main__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
import pyuv
1212

13-
class HashCache(object):
13+
class HashCache:
1414
def __init__(self, loop, excludePatterns, disableWatching):
1515
self._loop = loop
1616
self._watchedDirectories = {}
@@ -66,7 +66,7 @@ def isExcluded(self, dirname):
6666
return excluded
6767

6868

69-
class Connection(object):
69+
class Connection:
7070
def __init__(self, pipe, cache, onCloseCallback):
7171
self._readBuffer = b''
7272
self._pipe = pipe
@@ -92,7 +92,7 @@ def _onWriteDone(self, pipe, error):
9292
self._onCloseCallback(self)
9393

9494

95-
class PipeServer(object):
95+
class PipeServer:
9696
def __init__(self, loop, address, cache):
9797
self._pipeServer = pyuv.Pipe(loop)
9898
self._pipeServer.bind(address)

clcache/storage.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
CACHE_COMPILER_OUTPUT_STORAGE_CODEC
99

1010

11-
class CacheDummyLock(object):
11+
class CacheDummyLock:
1212
def __enter__(self):
1313
pass
1414

1515
def __exit__(self, typ, value, traceback):
1616
pass
1717

1818

19-
class CacheMemcacheStrategy(object):
19+
class CacheMemcacheStrategy:
2020
def __init__(self, server, cacheDirectory=None, manifestPrefix='manifests_', objectPrefix='objects_'):
2121
self.fileStrategy = CacheFileStrategy(cacheDirectory=cacheDirectory)
2222
# XX Memcache Strategy should be independent
@@ -156,7 +156,7 @@ def clean(self, stats, maximumSize):
156156
maximumSize)
157157

158158

159-
class CacheFileWithMemcacheFallbackStrategy(object):
159+
class CacheFileWithMemcacheFallbackStrategy:
160160
def __init__(self, server, cacheDirectory=None, manifestPrefix='manifests_', objectPrefix='objects_'):
161161
self.localCache = CacheFileStrategy(cacheDirectory=cacheDirectory)
162162
self.remoteCache = CacheMemcacheStrategy(server, cacheDirectory=cacheDirectory,

pyinstaller/clcache_main.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
1+
import multiprocessing
12
from clcache.__main__ import main
3+
multiprocessing.freeze_support()
24
main()

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
entry_points={
2323
'console_scripts': [
2424
'clcache = clcache.__main__:main',
25+
'cl.cache = clcache.__main__:main',
2526
'clcache-server = clcache.server.__main__:main',
2627
]
2728
},
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int somefunc() { return 1; }
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<ItemGroup Label="ProjectConfigurations">
4+
<ProjectConfiguration Include="Release|Win32">
5+
<Configuration>Release</Configuration>
6+
<Platform>Win32</Platform>
7+
</ProjectConfiguration>
8+
</ItemGroup>
9+
10+
<PropertyGroup Label="Configuration">
11+
<ConfigurationType>Application</ConfigurationType>
12+
</PropertyGroup>
13+
14+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
15+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
16+
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
17+
18+
<ItemDefinitionGroup>
19+
<ClCompile>
20+
<DebugInformationFormat>OldStyle</DebugInformationFormat>
21+
</ClCompile>
22+
</ItemDefinitionGroup>
23+
<ItemGroup>
24+
<ClCompile Include="another.cpp">
25+
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
26+
</ClCompile>
27+
<ClCompile Include="../minimal.cpp" />
28+
<ClCompile Include="../fibonacci.cpp" />
29+
</ItemGroup>
30+
</Project>

0 commit comments

Comments
 (0)