Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(402)

Side by Side Diff: gclient_utils.py

Issue 3107009: Move ExecutionQueue and WorkItem to gclient_utils.py (Closed)
Patch Set: Update unit test Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gclient.py ('k') | tests/gclient_utils_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2009 Google Inc. All Rights Reserved. 1 # Copyright 2009 Google Inc. All Rights Reserved.
2 # 2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); 3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License. 4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at 5 # You may obtain a copy of the License at
6 # 6 #
7 # http://www.apache.org/licenses/LICENSE-2.0 7 # http://www.apache.org/licenses/LICENSE-2.0
8 # 8 #
9 # Unless required by applicable law or agreed to in writing, software 9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, 10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and 12 # See the License for the specific language governing permissions and
13 # limitations under the License. 13 # limitations under the License.
14 14
15 """Generic utils.""" 15 """Generic utils."""
16 16
17 import errno 17 import errno
18 import logging 18 import logging
19 import os 19 import os
20 import re 20 import re
21 import stat 21 import stat
22 import subprocess 22 import subprocess
23 import sys 23 import sys
24 import time 24 import time
25 import threading
25 import xml.dom.minidom 26 import xml.dom.minidom
26 import xml.parsers.expat 27 import xml.parsers.expat
27 28
28 29
29 class CheckCallError(OSError): 30 class CheckCallError(OSError):
30 """CheckCall() returned non-0.""" 31 """CheckCall() returned non-0."""
31 def __init__(self, command, cwd, retcode, stdout, stderr=None): 32 def __init__(self, command, cwd, retcode, stdout, stderr=None):
32 OSError.__init__(self, command, cwd, retcode, stdout, stderr) 33 OSError.__init__(self, command, cwd, retcode, stdout, stderr)
33 self.command = command 34 self.command = command
34 self.cwd = cwd 35 self.cwd = cwd
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 config_path = FindFileUpwards(config_file, path) 357 config_path = FindFileUpwards(config_file, path)
357 358
358 if not config_path: 359 if not config_path:
359 print "Can't find %s" % config_file 360 print "Can't find %s" % config_file
360 return None 361 return None
361 362
362 env = {} 363 env = {}
363 execfile(config_path, env) 364 execfile(config_path, env)
364 config_dir = os.path.dirname(config_path) 365 config_dir = os.path.dirname(config_path)
365 return config_dir, env['entries'] 366 return config_dir, env['entries']
367
368
369 class WorkItem(object):
370 """One work item."""
371 # A list of string, each being a WorkItem name.
372 requirements = []
373 # A unique string representing this work item.
374 name = None
375
376 def run(self):
377 pass
378
379
380 class ExecutionQueue(object):
381 """Dependencies sometime needs to be run out of order due to From() keyword.
382
383 This class manages that all the required dependencies are run before running
384 each one.
385
386 Methods of this class are multithread safe.
387 """
388 def __init__(self, progress):
389 self.lock = threading.Lock()
390 # List of WorkItem, Dependency inherits from WorkItem.
391 self.queued = []
392 # List of strings representing each Dependency.name that was run.
393 self.ran = []
394 # List of items currently running.
395 self.running = []
396 self.progress = progress
397 if self.progress:
398 self.progress.update()
399
400 def enqueue(self, d):
401 """Enqueue one Dependency to be executed later once its requirements are
402 satisfied.
403 """
404 assert isinstance(d, WorkItem)
405 try:
406 self.lock.acquire()
407 self.queued.append(d)
408 total = len(self.queued) + len(self.ran) + len(self.running)
409 finally:
410 self.lock.release()
411 if self.progress:
412 self.progress._total = total + 1
413 self.progress.update(0)
414
415 def flush(self, *args, **kwargs):
416 """Runs all enqueued items until all are executed."""
417 while self._run_one_item(*args, **kwargs):
418 pass
419 queued = []
420 running = []
421 try:
422 self.lock.acquire()
423 if self.queued:
424 queued = self.queued
425 self.queued = []
426 if self.running:
427 running = self.running
428 self.running = []
429 finally:
430 self.lock.release()
431 if self.progress:
432 self.progress.end()
433 if queued:
434 raise gclient_utils.Error('Entries still queued: %s' % str(queued))
435 if running:
436 raise gclient_utils.Error('Entries still queued: %s' % str(running))
437
438 def _run_one_item(self, *args, **kwargs):
439 """Removes one item from the queue that has all its requirements completed
440 and execute it.
441
442 Returns False if no item could be run.
443 """
444 i = 0
445 d = None
446 try:
447 self.lock.acquire()
448 while i != len(self.queued) and not d:
449 d = self.queued.pop(i)
450 for r in d.requirements:
451 if not r in self.ran:
452 self.queued.insert(i, d)
453 d = None
454 break
455 i += 1
456 if not d:
457 return False
458 self.running.append(d)
459 finally:
460 self.lock.release()
461 d.run(*args, **kwargs)
462 try:
463 self.lock.acquire()
464 assert not d.name in self.ran
465 if not d.name in self.ran:
466 self.ran.append(d.name)
467 self.running.remove(d)
468 if self.progress:
469 self.progress.update(1)
470 finally:
471 self.lock.release()
472 return True
OLDNEW
« no previous file with comments | « gclient.py ('k') | tests/gclient_utils_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698