Pseudy code for design review only.
diff --git a/crosperf/testpiece.py b/crosperf/testpiece.py
new file mode 100644
index 0000000..4015f91
--- /dev/null
+++ b/crosperf/testpiece.py
@@ -0,0 +1,103 @@
+#!/usr/bin/python
+
+from benchmark import Benchmark
+from collections import defaultdict
+
+# Find Label for a DUT. This is done by iterating all the labels (usually < 10)
+# and compare each lable's image with Dut's image (how?) and also check DUT's
+# name against labels' remote (if presented). This could return None if a DUT
+# has an image that is not listed in any label.
+
+def FindLabelForDut(dut)
+ # ...
+ pass
+
+
+class DUT(object):
+
+ # Device under test.
+ # name_ - the hostname/ip of the machine
+ # label_ - the corresponding label or None.
+ # board_ - board (optional)
+
+ def __init__(self, name, board):
+ self.name_ = name
+ # Maybe None before any reimaging happens.
+ self.label_ = FindLabelForDut(self)
+
+ def ReImage(self, label):
+ call_utility_function_to_reimage(self, label)
+ self.label_ = label
+
+
+class TestPiece(object):
+
+ # Minimal units to be scheduled
+ # benchmark - as described in benchmark.py module
+ # nth - each TestPiece may run many times, this is the idx
+ # label - TestPiece run against
+
+ def __init__(self, benchmark, nth, label):
+ self.benchmark_ = benchmark
+ self.nth_ = nth
+ self.label_ = label
+
+
+class TestPiecePool(object):
+
+ # label_tpl_map_ - label to TestPiece list mapping.
+ # label_num_map_ - label to num of deployment mapping.
+
+ def __init__(self, test_piece_list):
+ self.label_tpl_map_ = defaultdict(lambda: [])
+ self.label_num_map_ = defaultdict(lambda: 0)
+ for tp in test_piece_list:
+ self.label_tpl_map_[tp.label_].append(tp)
+ self.label_num_map_[tp.label_] = 0
+
+ # This is usually called by multiple threads.
+
+ def GetTestPiece(self, dut):
+ tp = GetTestPieceInternal(self, dut)
+ while tp is None:
+ # The current dut image does not match any experiment labels,
+ # request reimage.
+ label = self.FindReImageCandidate(self)
+ if lable is None:
+ # We don't have any label that this machine can reimage to. On
+ # return, the dut thread will finish.
+ return None
+ dut.ReImage(label)
+ tp = GetTestPieceInternal(self, dut)
+ return tp
+
+ def _GetTestPieceInternal(self, dut):
+ if dut.label_ is not None and dut.label_ in self.label_tpl_map_:
+ tp_list = self.label_tpl_map_[dut.label_]
+ tp = None
+ ##### Lock on tp_list
+ if len(tp_list):
+ tp = tp_list.pop()
+ if not len(tp_list):
+ #### Lock on self.label_tpl_map_
+ del self.label_tpl_map_[dut.label]
+ #### Unlock on self.label_tpl_map_
+ ##### Unlock on tp_list
+ return tp
+ return None
+
+ def _FindReImageCandidate(self, dut):
+ # We will pick up the image desc with minimal deployment number.
+ minlabel, minnum = None, 999999
+ for label, num in self.label_num_map_.iteritems():
+ if (num < minnum and len(self.label_tpl_map_[label]) > 0 and
+ label.remote is None or dut.name_ in label.remote):
+ minlabel = label
+ minnum = num
+ if minlabel is not None:
+ #### Lock on self.label_num_map_
+ self.label_num_map_[minlabel] += 1
+ #### Unlock on self.label_num_map_
+
+ # minlabel may be None
+ return minlabel