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

Side by Side Diff: gft_hwcomp.py

Issue 6822028: factory_test_tools: improve gft_hwcomp (hardware_Components) performance (Closed) Base URL: ssh://gitrw.chromium.org:9222/factory_test_tools.git@master
Patch Set: add comments for why isolateing EC Created 9 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « gft_common.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # 2 #
3 # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. 3 # Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 import glob 7 import glob
8 import os 8 import os
9 import pprint 9 import pprint
10 import re 10 import re
11 import sys 11 import sys
12 import threading
12 13
13 import flashrom_util 14 import flashrom_util
14 import gft_common 15 import gft_common
15 import gft_fwhash 16 import gft_fwhash
16 import vblock 17 import vblock
17 18
18 from gft_common import DebugMsg, VerboseMsg, WarningMsg, ErrorMsg, ErrorDie 19 from gft_common import DebugMsg, VerboseMsg, WarningMsg, ErrorMsg, ErrorDie
19 20
20 21
21 def Memorize(f): 22 def Memorize(f):
22 """ Decorator for functions that need memorization.""" 23 return gft_common.ThreadSafe(gft_common.Memorize(f))
23 memorize_data = {}
24 def memorize_call(*args):
25 index = repr(args)
26 if index in memorize_data:
27 value = memorize_data[index]
28 # DebugMsg('Memorize: using cached value for: %s %s' % (repr(f), index))
29 return value
30 value = f(*args)
31 memorize_data[index] = value
32 return value
33 return memorize_call
34 24
35 25
36 class HardwareComponents(object): 26 class HardwareComponents(object):
37 """ Hardware Components Scanner """ 27 """ Hardware Components Scanner """
38 28
39 # Function names in this class are used for reflection, so please don't change 29 # Function names in this class are used for reflection, so please don't change
40 # the function names even if they are not comliant to coding style guide. 30 # the function names even if they are not comliant to coding style guide.
41 31
42 version = 5 32 version = 6
43 33
44 # We divide all component IDs (cids) into 5 categories: 34 # We divide all component IDs (cids) into 5 categories:
45 # - enumerable: able to get the results by running specific commands; 35 # - enumerable: able to get the results by running specific commands;
46 # - probable: returns existed or not by given some pre-defined choices; 36 # - probable: returns existed or not by given some pre-defined choices;
47 # - pure data: data for some special purpose, can't be tested; 37 # - pure data: data for some special purpose, can't be tested;
48 38
49 _enumerable_cids = [ 39 _enumerable_cids = [
50 'data_display_geometry', 40 'data_display_geometry',
51 'hash_ec_firmware', 41 'hash_ec_firmware',
52 'hash_ro_firmware', 42 'hash_ro_firmware',
(...skipping 28 matching lines...) Expand all
81 _probable_cids = [ 71 _probable_cids = [
82 'key_recovery', 72 'key_recovery',
83 'key_root', 73 'key_root',
84 'part_id_cardreader', 74 'part_id_cardreader',
85 ] 75 ]
86 _pure_data_cids = [ 76 _pure_data_cids = [
87 'data_bitmap_fv', 77 'data_bitmap_fv',
88 'data_recovery_url', 78 'data_recovery_url',
89 ] 79 ]
90 80
81 # list of cids that should not be fetched asynchronously.
82 _non_async_cids = [
83 # Reading EC will become very slow and cause inaccurate results if we try to
84 # probe components that also fires EC command at the same time.
85 'part_id_ec_flash_chip',
86 ]
87
91 # _not_test_cids and _to_be_tested_cids will be re-created for each match. 88 # _not_test_cids and _to_be_tested_cids will be re-created for each match.
92 _not_test_cids = [] 89 _not_test_cids = []
93 _to_be_tested_cids = [] 90 _to_be_tested_cids = []
94 91
95 # TODO(hungte) unify the 'not available' style messages 92 # TODO(hungte) unify the 'not available' style messages
96 _not_present = '' 93 _not_present = ''
97 _no_match = 'No match' 94 _no_match = 'No match'
98 95
99 def __init__(self, verbose=False): 96 def __init__(self, verbose=False):
100 self._initialized = False 97 self._initialized = False
(...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 def read_approved_from_file(self, filename): 623 def read_approved_from_file(self, filename):
627 approved = gft_common.LoadComponentsDatabaseFile(filename) 624 approved = gft_common.LoadComponentsDatabaseFile(filename)
628 for cid in self._to_be_tested_cids + self._not_test_cids: 625 for cid in self._to_be_tested_cids + self._not_test_cids:
629 if cid not in approved: 626 if cid not in approved:
630 # If we don't have any listing for this type 627 # If we don't have any listing for this type
631 # of part in HWID, it's not required. 628 # of part in HWID, it's not required.
632 WarningMsg('gft_hwcomp: Bypassing unlisted cid %s' % cid) 629 WarningMsg('gft_hwcomp: Bypassing unlisted cid %s' % cid)
633 approved[cid] = '*' 630 approved[cid] = '*'
634 return approved 631 return approved
635 632
636 def get_all_enumerable_components(self): 633 def get_all_enumerable_components(self, async):
637 results = {} 634 results = {}
638 for cid in self._enumerable_cids: 635 thread_pools = []
636
637 def fetch_enumerable_component(cid):
638 """ Fetch an enumerable component and update the results """
639 if self._verbose: 639 if self._verbose:
640 sys.stdout.flush() 640 sys.stdout.flush()
641 sys.stderr.write('<Fetching property %s>\n' % cid) 641 sys.stderr.write('<Fetching property %s>\n' % cid)
642 components = self.force_get_property('get_' + cid) 642 components = self.force_get_property('get_' + cid)
643 if not isinstance(components, list): 643 if not isinstance(components, list):
644 components = [components] 644 components = [components]
645 results[cid] = components 645 results[cid] = components
646
647 class FetchThread(threading.Thread):
648 """ Thread object for parallel enumerating """
649 def __init__(self, cid):
650 threading.Thread.__init__(self)
651 self.cid = cid
652
653 def run(self):
654 fetch_enumerable_component(self.cid)
655
656 for cid in self._enumerable_cids:
657 if async and cid not in self._non_async_cids:
658 thread_pools.append(FetchThread(cid))
659 else:
660 fetch_enumerable_component(cid)
661
662 # Complete the threads
663 for thread in thread_pools:
664 thread.start()
665 for thread in thread_pools:
666 thread.join()
646 return results 667 return results
647 668
648 def check_enumerable_component(self, cid, exact_values, approved_values): 669 def check_enumerable_component(self, cid, exact_values, approved_values):
649 if '*' in approved_values: 670 if '*' in approved_values:
650 return 671 return
651 672
652 for value in exact_values: 673 for value in exact_values:
653 if value not in approved_values: 674 if value not in approved_values:
654 if cid in self._failures: 675 if cid in self._failures:
655 self._failures[cid].append(value) 676 self._failures[cid].append(value)
(...skipping 14 matching lines...) Expand all
670 def check_probable_component(self, cid, approved_values): 691 def check_probable_component(self, cid, approved_values):
671 (probed, value) = self.verify_probable_component(cid, approved_values) 692 (probed, value) = self.verify_probable_component(cid, approved_values)
672 if probed: 693 if probed:
673 self._system[cid] = value 694 self._system[cid] = value
674 else: 695 else:
675 self._failures[cid] = value 696 self._failures[cid] = value
676 697
677 def pformat(self, obj): 698 def pformat(self, obj):
678 return '\n' + self._pp.pformat(obj) + '\n' 699 return '\n' + self._pp.pformat(obj) + '\n'
679 700
680 def initialize(self, force=False): 701 def initialize(self, force=False, async=False):
681 if self._initialized and not force: 702 if self._initialized and not force:
682 return 703 return
683 # probe current system components 704 # probe current system components
684 DebugMsg('Starting to detect system components...') 705 DebugMsg('Starting to detect system components...')
685 self._enumerable_system = self.get_all_enumerable_components() 706 self._enumerable_system = self.get_all_enumerable_components(async)
686 self._initialized = True 707 self._initialized = True
687 708
688 def match_current_system(self, filename, ignored_cids=[]): 709 def match_current_system(self, filename, ignored_cids=[]):
689 """ Matches a given component list to current system. 710 """ Matches a given component list to current system.
690 Returns: (current, failures) 711 Returns: (current, failures)
691 """ 712 """
692 713
693 # assert self._initialized, 'Not initialized.' 714 # assert self._initialized, 'Not initialized.'
694 self._to_be_tested_cids = (self._enumerable_cids + 715 self._to_be_tested_cids = (self._enumerable_cids +
695 self._probable_cids) 716 self._probable_cids)
(...skipping 18 matching lines...) Expand all
714 else: 735 else:
715 self.check_probable_component(cid, approved[cid]) 736 self.check_probable_component(cid, approved[cid])
716 737
717 return (self._system, self._failures) 738 return (self._system, self._failures)
718 739
719 740
720 ############################################################################# 741 #############################################################################
721 # Console main entry 742 # Console main entry
722 @gft_common.GFTConsole 743 @gft_common.GFTConsole
723 def _main(self_path, args): 744 def _main(self_path, args):
724 if not args: 745 do_async = True
725 print 'Usage: %s components_db_files...\n' % self_path 746
726 sys.exit(1) 747 # preprocess args
748 compdb_list = []
749 for arg in args:
750 if arg == '--sync':
751 do_async = False
752 elif arg == '--async':
753 do_async = True
754 elif not os.path.exists(arg):
755 print 'ERROR: unknown parameter: ' + arg
756 print 'Usage: %s [--sync|--async] [components_db_files...]\n' % self_path
757 sys.exit(1)
758 else:
759 compdb_list.append(arg)
760
727 components = HardwareComponents(verbose=True) 761 components = HardwareComponents(verbose=True)
728 print 'Starting to probe system...' 762 print 'Starting to detect %s...' % ('Asynchronously' if do_async else '')
Tom Wai-Hong Tam 2011/04/13 01:19:36 Asynchronously -> asynchronously
729 components.initialize() 763 components.initialize(async=do_async)
764
765 if not compdb_list:
766 print 'Enumerable properties:'
767 print components.pformat(components._enumerable_system)
768 sys.exit(0)
769
730 print 'Starting to match system...' 770 print 'Starting to match system...'
731 771 for arg in compdb_list:
732 for arg in args:
733 (matched, failures) = components.match_current_system(arg) 772 (matched, failures) = components.match_current_system(arg)
734 print 'Probed (%s):' % arg 773 print 'Probed (%s):' % arg
735 print components.pformat(matched) 774 print components.pformat(matched)
736 print 'Failures (%s):' % arg 775 print 'Failures (%s):' % arg
737 print components.pformat(failures) 776 print components.pformat(failures)
738 777
739 if __name__ == '__main__': 778 if __name__ == '__main__':
740 _main(sys.argv[0], sys.argv[1:]) 779 _main(sys.argv[0], sys.argv[1:])
OLDNEW
« no previous file with comments | « gft_common.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698