summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/usr/targeting/attributeenums.H1
-rw-r--r--src/include/usr/targeting/iterators/rangefilter.H323
-rw-r--r--src/include/usr/targeting/iterators/targetiterator.H257
-rw-r--r--src/include/usr/targeting/predicates/predicatebase.H111
-rw-r--r--src/include/usr/targeting/predicates/predicatectm.H118
-rw-r--r--src/include/usr/targeting/predicates/predicatepostfixexpr.H204
-rw-r--r--src/include/usr/targeting/targetservice.H95
-rw-r--r--src/usr/targeting/iterators/rangefilter.C89
-rw-r--r--src/usr/targeting/iterators/targetiterator.C88
-rw-r--r--src/usr/targeting/makefile21
-rw-r--r--src/usr/targeting/predicates/predicatebase.C54
-rw-r--r--src/usr/targeting/predicates/predicatectm.C63
-rw-r--r--src/usr/targeting/predicates/predicatepostfixexpr.C198
-rw-r--r--src/usr/targeting/targetservice.C108
-rw-r--r--src/usr/targeting/test/targetingtest.H533
-rw-r--r--src/usr/targeting/trace.H2
16 files changed, 2224 insertions, 41 deletions
diff --git a/src/include/usr/targeting/attributeenums.H b/src/include/usr/targeting/attributeenums.H
index c4cd5c28a..6d7eed93d 100644
--- a/src/include/usr/targeting/attributeenums.H
+++ b/src/include/usr/targeting/attributeenums.H
@@ -34,6 +34,7 @@ namespace TARGETING
*/
enum ATTRIBUTE_ID
{
+ ATTR_NA = 0x00,
ATTR_CLASS = 0x01,
ATTR_TYPE = 0x02,
ATTR_MODEL = 0x03,
diff --git a/src/include/usr/targeting/iterators/rangefilter.H b/src/include/usr/targeting/iterators/rangefilter.H
new file mode 100644
index 000000000..b582cb0b6
--- /dev/null
+++ b/src/include/usr/targeting/iterators/rangefilter.H
@@ -0,0 +1,323 @@
+
+#ifndef TARG_RANGEFILTER_H
+#define TARG_RANGEFILTER_H
+
+/**
+ * @file rangefilter.H
+ *
+ * @brief Interface describing an object which takes an iterator range and
+ * allows caller to iterate through the elements which match a supplied
+ * predicate (filter)
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+
+// STD
+
+// Other Host Boot Components
+
+// Targeting Component
+#include <targeting/target.H>
+#include <targeting/predicates/predicatebase.H>
+#include <targeting/iterators/targetiterator.H>
+
+//******************************************************************************
+// Macros
+//******************************************************************************
+
+#undef TARG_NAMESPACE
+#undef TARG_CLASS
+#undef TARG_FUNC
+
+//******************************************************************************
+// Interface
+//******************************************************************************
+
+namespace TARGETING
+{
+
+#define TARG_NAMESPACE "TARGETING::"
+
+#define TARG_CLASS "RangeFilter<IteratorType>::"
+
+/**
+ * @brief Templated class which which takes an iterator range of arbitrary type
+ * and allows caller to iterate through the elements which match a supplied
+ * predicate (filter)
+ */
+template<typename IteratorType>
+class RangeFilter
+{
+ public:
+
+ /**
+ * @var Forward the type of iterated elements to help build the
+ * class generically
+ */
+ typedef typename IteratorType::value_type value_type;
+
+ /**
+ * @var fake_bool is a pointer to a member function of RangeFilter
+ * which takes no arguments and returns void.
+ * Used to implement ability to check if range iterator is valid
+ */
+ typedef void (RangeFilter::*fake_bool)() const;
+
+ /**
+ * @brief Create a range object and locate first item in the range that
+ * matches the predicate (or the first if no predicate)
+ *
+ * @param[in] i_begin Iterator pointing to first item in range
+ * @param[in] i_end Iterator pointing to last item in range
+ * @param[in] i_pPredicate Predicate evaluated against each pointed to
+ * item
+ *
+ * @note Begin iterator must point to element prior to end iterator,
+ * otherwise result is undefined
+ */
+ RangeFilter(
+ const IteratorType& i_begin,
+ const IteratorType& i_end,
+ const PredicateBase* i_pPredicate = NULL);
+
+ /**
+ * @brief Destroy a range object (nothing to do)
+ */
+ ~RangeFilter()
+ {
+ }
+
+ /**
+ * @brief Dummy function used to implement ability to check if range
+ * iterator is valid
+ */
+ operator fake_bool() const
+ {
+ return (iv_current != iv_end)
+ ? &RangeFilter::notComparable : NULL;
+ }
+
+ /**
+ * @brief Pre-increment operator which advances the range's iterator
+ * to point to the next valid element
+ *
+ * @return Reference to this range filter
+ */
+ RangeFilter& operator++();
+
+ /**
+ * @brief Dereference the range filter, returning the element pointed
+ *
+ * @return The element pointed to by the range filter
+ */
+ value_type operator*() const
+ {
+ return *iv_current;
+ }
+
+ /**
+ * @brief Dereference the range filter, returning the element pointed
+ * for use by the dereference and call member operator
+ *
+ * @return The element pointed to by the range filter
+ */
+ value_type operator->() const
+ {
+ return *iv_current;
+ }
+
+ /**
+ * @brief Reset the range's internal iterator to point to the first
+ * item in the range that matches the predicate (or the first if no
+ * predicate)
+ */
+ void reset();
+
+ /**
+ * @brief Set the range's predicate filter
+ *
+ * @param[in] i_pPredicate Predicate to evaluate against elements
+ * pointed to by the range
+ */
+ void setPredicate(
+ const PredicateBase* i_pPredicate);
+
+ /**
+ * @brief Assignment operator; assign one range filter to another
+ *
+ * @param[in] i_rhs Range filter to assign
+ */
+ RangeFilter& operator=(
+ const RangeFilter& i_rhs);
+
+ /**
+ * @brief Copy constructor; create range filter using another range
+ * filter as a prototype for it
+ *
+ * @param[in] i_rhs Range filter to assign on create
+ */
+ RangeFilter(
+ const RangeFilter& i_rhs);
+
+ private:
+
+ /**
+ * @brief Update internal cursor to point to the next element of the
+ * underlying range
+ *
+ * @note If the internal cursor is at the end of the range, then do
+ * nothing
+ */
+ void advance();
+
+ /**
+ * @brief Update internal cursor to point to the next element of the
+ * underlying range only if not past the end of the range and the
+ * predicate doesn't match the current item
+ *
+ * @note If the internal cursor is at the end of the range, then do
+ * nothing
+ */
+ void advanceIfNoMatch();
+
+ /**
+ * @brief Dummy function used to implement ability to check if range
+ * iterator is valid
+ */
+ void notComparable() const
+ {
+ }
+
+ IteratorType iv_current; ///< Iterator pointing to the
+ ///< current element
+ IteratorType iv_begin; ///< Iterator pointing to first
+ ///< element in range
+ IteratorType iv_end; ///< Iterator to past the end
+ ///< element in range
+ const PredicateBase* iv_pPredicate; ///< Range filter
+};
+
+typedef RangeFilter<TargetIterator> TargetRangeFilter;
+typedef RangeFilter<ConstTargetIterator> ConstTargetRangeFilter;
+
+//******************************************************************************
+// RangeFilter::RangeFilter
+//******************************************************************************
+
+template<typename IteratorType>
+RangeFilter<IteratorType>::RangeFilter(
+ const IteratorType& i_begin,
+ const IteratorType& i_end,
+ const PredicateBase* const i_pPredicate)
+: iv_current(i_begin),
+ iv_begin(i_begin),
+ iv_end(i_end),
+ iv_pPredicate(i_pPredicate)
+{
+ advanceIfNoMatch();
+}
+
+//******************************************************************************
+// RangeFilter::operator=
+//******************************************************************************
+
+template<typename IteratorType>
+RangeFilter<IteratorType>& RangeFilter<IteratorType>::operator=(
+ const RangeFilter& i_rhs)
+{
+ iv_current = i_rhs.iv_current;
+ iv_begin = i_rhs.iv_begin;
+ iv_end = i_rhs.iv_end;
+ iv_pPredicate = i_rhs.iv_pPredicate;
+}
+
+//******************************************************************************
+// RangeFilter::RangeFilter (copy constructor)
+//******************************************************************************
+
+template<typename IteratorType>
+RangeFilter<IteratorType>::RangeFilter(
+ const RangeFilter& i_rhs)
+: iv_current(i_rhs.iv_current),
+ iv_begin(i_rhs.iv_begin),
+ iv_end(i_rhs.iv_end),
+ iv_pPredicate(i_rhs.iv_pPredicate)
+{
+}
+
+//******************************************************************************
+// RangeFilter::setPredicate
+//******************************************************************************
+
+template<typename IteratorType>
+void RangeFilter<IteratorType>::setPredicate(
+ const PredicateBase* const i_pPredicate)
+{
+ iv_pPredicate = i_pPredicate;
+ advanceIfNoMatch();
+}
+
+//******************************************************************************
+// RangeFilter::reset
+//******************************************************************************
+
+template<typename IteratorType>
+void RangeFilter<IteratorType>::reset()
+{
+ iv_current = iv_begin;
+ advanceIfNoMatch();
+}
+
+//******************************************************************************
+// RangeFilter::operator++
+//******************************************************************************
+
+template<typename IteratorType>
+RangeFilter<IteratorType>& RangeFilter<IteratorType>::operator++()
+{
+ advance();
+ return *this;
+}
+
+/**
+ * @brief Disable meaningless "bool" comparisons that can occur when
+ * evaluating a range as a bool by forcing a compilation failure.
+ * Function interfaces not documented since they are not used.
+ */
+template <typename T>
+bool operator!=(const TargetRangeFilter& i_lhs, const T& i_rhs)
+{
+ i_lhs.notComparable();
+ return false;
+}
+
+template <typename T>
+bool operator==(const TargetRangeFilter& i_lhs, const T& i_rhs)
+{
+ i_lhs.notComparable();
+ return false;
+}
+
+template <typename T>
+bool operator!=(const ConstTargetRangeFilter& i_lhs, const T& i_rhs)
+{
+ i_lhs.notComparable();
+ return false;
+}
+
+template <typename T>
+bool operator==(const ConstTargetRangeFilter& i_lhs, const T& i_rhs)
+{
+ i_lhs.notComparable();
+ return false;
+}
+
+#undef TARG_CLASS
+#undef TARG_NAMESPACE
+
+} // End namespace TARGETING
+
+#endif
+
diff --git a/src/include/usr/targeting/iterators/targetiterator.H b/src/include/usr/targeting/iterators/targetiterator.H
new file mode 100644
index 000000000..6f250cbb5
--- /dev/null
+++ b/src/include/usr/targeting/iterators/targetiterator.H
@@ -0,0 +1,257 @@
+
+#ifndef TARG_TARGETITERATOR_H
+#define TARG_TARGETITERATOR_H
+
+/**
+ * @file targetiterator.H
+ *
+ * @brief Interface describing iterator/const iterator used to iterate through
+ * target service targets
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+
+// STD
+#include <stddef.h>
+
+// Other Host Boot Components
+#include <builtins.h>
+
+// Targeting Component
+
+//******************************************************************************
+// Macros
+//******************************************************************************
+
+#undef TARG_NAMESPACE
+#undef TARG_CLASS
+#undef TARG_FUNC
+
+//******************************************************************************
+// Interface
+//******************************************************************************
+
+namespace TARGETING
+{
+
+#define TARG_NAMESPACE "TARGETING::"
+
+#define TARG_CLASS "_TargetIterator<T>::"
+
+class Target;
+
+/**
+ * @brief Class which iterates through targets managed by the target service.
+ * Provides "Target*" and "const Target*" versions via templates
+ */
+template<typename T>
+class _TargetIterator
+{
+ public:
+
+ /**
+ * @brief Maps type of iterated element to common alias (Target* or
+ * const Target*)
+ */
+ typedef T iterator;
+ typedef T value_type;
+
+ /**
+ * @brief Create an iterator to a (const/non-const) target handle.
+ * Defaults to end()
+ */
+ ALWAYS_INLINE
+ _TargetIterator()
+ : iv_pCurrent(NULL)
+ {
+ }
+
+ /**
+ * @brief Create an iterator to a (const/non-const) target handle
+ *
+ * @param[in] i_pTarget Target handle (pointer or const pointer
+ * depending on flavor) the iterator should reference
+ */
+ ALWAYS_INLINE
+ explicit _TargetIterator(T i_pTarget)
+ : iv_pCurrent(i_pTarget)
+ {
+ }
+
+ /**
+ * @brief Destroy an iterator to a (const/non-const) target handle
+ *
+ * @note Iterator does not own any resources to destroy
+ */
+ ALWAYS_INLINE
+ ~_TargetIterator()
+ {
+ }
+
+ /**
+ * @brief Dereference the iterator (return what it points to)
+ *
+ * @return Target handle in form of Target* or const Target*
+ *
+ * @note Returns NULL if it points to end(), should not be
+ * dereferenced in this case.
+ */
+ ALWAYS_INLINE
+ T operator* () const
+ {
+ // Only return copy of the target pointer (instead of a reference)
+ // because a reference will go out of scope when the iterator
+ // advances
+ return iv_pCurrent;
+ }
+
+ /**
+ * @brief Dereference the iterator (return what it points to)
+ * and (outside this function) call a function/member of
+ * the referenced target
+ *
+ * @return Target handle in form of Target* or const Target*
+ *
+ * @note Returns NULL if it points to end(), causing an
+ * assert when automatically dereferenced.
+ */
+ ALWAYS_INLINE
+ T operator->() const
+ {
+ // Only return copy of the target pointer (instead of a reference)
+ // because a reference will go out of scope when the iterator
+ // advances
+ return iv_pCurrent;
+ }
+
+ /**
+ * @brief Pre-increment the iterator
+ *
+ * @return The reference to the same iterator after advancing it
+ */
+ ALWAYS_INLINE
+ _TargetIterator& operator++();
+
+ /**
+ * @brief Post-increment the iterator
+ *
+ * @param[in] UNNAMED Dummy parameter used to distinguish
+ * this interface from pre-increment
+ *
+ * @return Copy of the original iterator before it advanced
+ */
+ ALWAYS_INLINE
+ _TargetIterator operator++(int);
+
+ /**
+ * @brief Determine if two iterators of same type are logically equal
+ *
+ * @param[in] i_rhs The other iterator to compare
+ *
+ * @return bool indicating whether the iterators point to the same
+ * entity
+ *
+ * @retval true Iterators point to same entity
+ * @retval false Iterators do not point to same entity
+ */
+ ALWAYS_INLINE
+ bool operator==(const _TargetIterator& i_rhs) const
+ {
+ return (iv_pCurrent == i_rhs.iv_pCurrent);
+ }
+
+ /**
+ * @brief Determine if two iterators of same type are logically not
+ * equal
+ *
+ * @param[in] i_rhs The other iterator to compare
+ *
+ * @return bool indicating whether the iterators point to a different
+ * logical entity
+ *
+ * @retval true Iterators point to different entity
+ * @retval false Iterators point to same entity
+ */
+ ALWAYS_INLINE
+ bool operator!=(const _TargetIterator& i_rhs) const
+ {
+ return (iv_pCurrent != i_rhs.iv_pCurrent);
+ }
+
+ /**
+ * @brief Assignment operator; assign iterator to another (such that
+ * they logically point to same entity)
+ *
+ * @param[in] i_rhs The iterator to assign
+ *
+ * @return Reference to the iterator, now updated to point to the same
+ * entity as the input iterator points to
+ */
+ ALWAYS_INLINE
+ _TargetIterator& operator=(const _TargetIterator& i_rhs)
+ {
+ iv_pCurrent = i_rhs.iv_pCurrent;
+ return *this;
+ }
+
+ /**
+ * @brief Copy constructor; assign iterator to a new iterator (such
+ * that they logically point to same entity)
+ *
+ * @param[in] i_rhs The iterator to assign
+ */
+ ALWAYS_INLINE
+ _TargetIterator(const _TargetIterator& i_rhs)
+ : iv_pCurrent(i_rhs.iv_pCurrent)
+ {
+ }
+
+ private:
+
+ /**
+ * @brief Advance the iterator to point to the next item maintained by
+ * the target service (or end() if end of list)
+ */
+ void advance();
+
+ T iv_pCurrent; // Pointer to current target
+};
+
+/**
+ * @brief Type aliases to simplify user code
+ */
+typedef _TargetIterator<Target*> TargetIterator;
+typedef _TargetIterator<const Target*> ConstTargetIterator;
+
+//******************************************************************************
+// _TargetIterator::operator++ (postincrement)
+//******************************************************************************
+
+template<typename T>
+_TargetIterator<T> _TargetIterator<T>::operator++(int)
+{
+ _TargetIterator l_originalIterator(*this);
+ advance();
+ return l_originalIterator;
+}
+
+//******************************************************************************
+// _TargetIterator::operator++ (preincrement)
+//******************************************************************************
+
+template<typename T>
+_TargetIterator<T>& _TargetIterator<T>::operator++()
+{
+ advance();
+ return *this;
+}
+
+#undef TARG_CLASS
+#undef TARG_NAMESPACE
+
+} // End namespace TARGETING
+
+#endif // TARG_TARGETITERATOR_H
+
diff --git a/src/include/usr/targeting/predicates/predicatebase.H b/src/include/usr/targeting/predicates/predicatebase.H
new file mode 100644
index 000000000..e555092b9
--- /dev/null
+++ b/src/include/usr/targeting/predicates/predicatebase.H
@@ -0,0 +1,111 @@
+
+#ifndef TARG_PREDICATEBASE_H
+#define TARG_PREDICATEBASE_H
+
+/**
+ * @file predicatebase.H
+ *
+ * @brief Interface for an abstract targeting predicate which filters a set of
+ * targets based on the programmed criteria. Concrete predicates must
+ * provide the interface specified here.
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+
+// STD
+
+// Other Host Boot Components
+
+// Targeting Component
+
+//******************************************************************************
+// Macros
+//******************************************************************************
+
+/**
+ * @brief Disable copy constructor / assignment operators
+ */
+#undef TARG_DISABLE_COPY_AND_ASSIGNMENT_OPERATORS
+#define TARG_DISABLE_COPY_AND_ASSIGNMENT_OPERATORS(Type) \
+ Type(const Type& i_other); \
+ Type& operator=(const Type& i_other)
+
+/**
+ * @brief Ensure trace macros are undefined
+ */
+#undef TARG_NAMESPACE
+#undef TARG_CLASS
+#undef TARG_FN
+
+//******************************************************************************
+// Interface
+//******************************************************************************
+
+namespace TARGETING
+{
+
+#define TARG_NAMESPACE "TARGETING::"
+#define TARG_CLASS "PredicateBase::"
+
+class Target;
+
+/**
+ * @brief Abstract predicate class which specifies an interface for all
+ * concrete predicates. A predicate acts as a filter on a set of targets.
+ */
+class PredicateBase
+{
+ public:
+
+ /**
+ * @brief Destroys the predicate base class (nothing to do)
+ */
+ virtual ~PredicateBase();
+
+ /**
+ * @brief Predicate function call interface
+ *
+ * @par Detailed Description:
+ * This abstract interface must be declared/implemented by all
+ * derived predicates. A concrete version of this function accepts
+ * a target, applies the associated predicate logic, and returns
+ * whether the target met the predicate criteria or not. Caller
+ * must always supply a valid Target*, or routine will assert.
+ *
+ * @param[in] i_pTarget Pointer to target to apply predicate to
+ *
+ * @return Boolean indicating whether target matches criteria specified
+ * by the concrete predicate
+ *
+ * @retval true Target matches the predicate criteria
+ * @retval false Target does not match the predicate criteria
+ */
+ virtual bool operator()(
+ const Target* i_pTarget) const = 0;
+
+ protected:
+
+ /**
+ * @brief Create the predicate base class (nothing to do)
+ *
+ * @note Constructor protected to allow access from the derived class
+ */
+ PredicateBase()
+ {
+ #define TARG_FN "PredicateBase()"
+ #undef TARG_FN
+ }
+
+ private:
+
+ TARG_DISABLE_COPY_AND_ASSIGNMENT_OPERATORS(PredicateBase);
+};
+
+#undef TARG_CLASS
+#undef TARG_NAMESPACE
+
+} // End namespace TARGETING
+
+#endif // TARG_PREDICATEBASE_H
diff --git a/src/include/usr/targeting/predicates/predicatectm.H b/src/include/usr/targeting/predicates/predicatectm.H
new file mode 100644
index 000000000..760f0d02d
--- /dev/null
+++ b/src/include/usr/targeting/predicates/predicatectm.H
@@ -0,0 +1,118 @@
+
+#ifndef TARG_PREDICATECTM_H
+#define TARG_PREDICATECTM_H
+
+/**
+ * @file predicatectm.H
+ *
+ * @brief Interface for a predicate which fiters a target based on its class,
+ * type, and model.
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+
+// STD
+
+// Other Host Boot Components
+
+// Targeting Component
+#include <targeting/target.H>
+#include <targeting/attributeenums.H>
+#include <targeting/predicates/predicatebase.H>
+
+//******************************************************************************
+// Macros
+//******************************************************************************
+
+#undef TARG_NAMESPACE
+#undef TARG_CLASS
+#undef TARG_FN
+
+//******************************************************************************
+// Interface
+//******************************************************************************
+
+namespace TARGETING
+{
+
+#define TARG_NAMESPACE "TARGETING::"
+#define TARG_CLASS "PredicateCTM::"
+
+class Target;
+
+/**
+ * @brief Predicate class which filters a target based on its class, type,
+ * and model
+ */
+class PredicateCTM : public PredicateBase
+{
+ public:
+
+ /**
+ * @brief Create a target class, type, model predicate
+ *
+ * @param[in] i_class Class of matching target, default NA (any)
+ * @param[in] i_type Type of matching target, default NA (any)
+ * @param[in] i_model Model of matching target, default NA (any)
+ */
+ PredicateCTM(
+ CLASS i_class = CLASS_NA,
+ TYPE i_type = TYPE_NA,
+ MODEL i_model = MODEL_NA);
+
+ /**
+ * @brief Destroy a class, type, model predicate
+ */
+ virtual ~PredicateCTM()
+ {
+ #define TARG_FUNC "~PredicateCTM()"
+ #undef TARG_FUNC
+ }
+
+ /**
+ * @brief Returns whether target matches the specified class, type,
+ * model
+ *
+ * @par Detailed Description:
+ * Returns whether target matches the specified class, type, model.
+ * Note that all three fields are always compared, so wildcards
+ * (CLASS_NA, TYPE_NA, MODEL_NA) must be used for any fields that
+ * do not matter. See PredicateBase class for parameter/return
+ * description.
+ */
+ virtual bool operator()(
+ const Target* i_pTarget) const;
+
+ private:
+
+ CLASS iv_class; ///< Class to compare with that of target
+ TYPE iv_type; ///< Type to compare with that of target
+ MODEL iv_model; ///< Model to compare with that of target
+
+ TARG_DISABLE_COPY_AND_ASSIGNMENT_OPERATORS(PredicateCTM);
+};
+
+//******************************************************************************
+// PredicateCTM::PredicateCTM
+//******************************************************************************
+
+inline PredicateCTM::PredicateCTM(
+ const CLASS i_class,
+ const TYPE i_type,
+ const MODEL i_model)
+: iv_class(i_class),
+ iv_type(i_type),
+ iv_model(i_model)
+{
+ #define TARG_FUNC "PredicateCTM(...)"
+ #undef TARG_FUNC
+}
+
+#undef TARG_CLASS
+#undef TARG_NAMESPACE
+
+} // End namespace TARGETING
+
+#endif // TARG_PREDICATECTM_H
diff --git a/src/include/usr/targeting/predicates/predicatepostfixexpr.H b/src/include/usr/targeting/predicates/predicatepostfixexpr.H
new file mode 100644
index 000000000..12388fc46
--- /dev/null
+++ b/src/include/usr/targeting/predicates/predicatepostfixexpr.H
@@ -0,0 +1,204 @@
+
+#ifndef TARG_PREDICATEPOSTFIXEXPR_H
+#define TARG_PREDICATEPOSTFIXEXPR_H
+
+/**
+ * @file predicatepostfixexpr.H
+ *
+ * @brief Interface for predicate which allows callers to chain multiple other
+ * predicates together in complex logical expressions, and then evaluate
+ * them against a target
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+
+// STD
+#include <vector>
+
+// Other Host Boot Components
+
+// Targeting Component
+#include <targeting/predicates/predicatebase.H>
+
+//******************************************************************************
+// Macros
+//******************************************************************************
+
+#undef TARG_NAMESPACE
+#undef TARG_CLASS
+#undef TARG_FN
+
+//******************************************************************************
+// Interface
+//******************************************************************************
+
+namespace TARGETING
+{
+
+#define TARG_NAMESPACE "TARGETING::"
+#define TARG_CLASS "PredicatePostfixExpr::"
+
+class Target;
+
+/**
+ * @brief Predicate which can compute aribtrarily complex logical expressions
+ * of other predicates using postfix notation
+ */
+class PredicatePostfixExpr : public PredicateBase
+{
+ public:
+
+ /**
+ * @brief Create empty postfix predicate expression which will always
+ * evaluate true if not otherwise modified. Any updates to the
+ * expression completely replace the initial "always true"
+ * behavior.
+ */
+ PredicatePostfixExpr();
+
+ /**
+ * @brief Destroy a postfix predicate expression
+ *
+ * @note: Nothing extra to do here since object does not own the
+ * predicates
+ */
+ virtual ~PredicatePostfixExpr();
+
+ /**
+ * @brief Updates the postfix predicate expression by pushing the given
+ * predicate onto the expression stack
+ *
+ * @param[in] i_pPredicate Pointer to existing concrete predicate.
+ * Passing a NULL predicate is not allowed (results in assert)
+ *
+ * @verbatim
+ * Example:
+ *
+ * Stack before calling push(&P2): P1
+ * Stack after calling push(&P2): P1 P2
+ * @endverbatim
+ *
+ * @return Reference to the same predicate expression, for chaining
+ */
+ PredicatePostfixExpr& push(
+ const PredicateBase* i_pPredicate);
+
+ /**
+ * @brief Updates the postfix predicate expression by pushing the
+ * logical "AND" operation onto the expression stack.
+ *
+ * @verbatim
+ * Example:
+ *
+ * Stack before calling And(): P1 P2
+ * Stack after calling And(): P1 P2 AND
+ * Stack after evaluation: (P1 && P2)
+ * @endverbatim
+ *
+ * @return Reference to the same predicate expression, for chaining
+ */
+ PredicatePostfixExpr& And();
+
+ /**
+ * @brief Updates the postfix predicate expression by pushing the
+ * logical "NOT" operation onto the expression stack.
+ *
+ * @verbatim
+ * Example:
+ *
+ * Stack before calling Not(): P1
+ * Stack after calling Not(): P1 NOT
+ * Stack after evaluation: (!P1)
+ * @endverbatim
+ *
+ * @return Reference to the same predicate expression, for chaining
+ */
+ PredicatePostfixExpr& Not();
+
+ /**
+ * @brief Updates the postfix predicate expression by pushing the
+ * logical "OR" operation onto the expression stack.
+ *
+ * @verbatim
+ * Example:
+ *
+ * Stack before calling Or(): P1 P2
+ * Stack after calling Or(): P1 P2 OR
+ * Stack after evaluation: (P1 || P2)
+ * @endverbatim
+ *
+ * @return Reference to the same predicate expression for chaining
+ */
+ PredicatePostfixExpr& Or();
+
+ /**
+ * @brief Returns whether the given target matches the criteria
+ * specified by the postfix predicate expression
+ *
+ * @par Detailed Description:
+ * Returns whether the given target matches the criteria
+ * specified by the postfix predicate expression. The routine
+ * sequentially evaluates a predicate against the supplied target
+ * or applies a logical operation to one or more prior predicate
+ * evaluations using a postfix algorithm. Routine will assert
+ * if postfix expression is not formatted properly, final result
+ * stack does not have exactly one result, target is NULL, or
+ * invalid logical operator was requested. See PredicateBase class
+ * for parameter/return description.
+ *
+ * @verbatim
+ * Example:
+ *
+ * PredicatePostfixExpr l_expr;
+ * l_expr.push(&P1).push(&P2).Or().push(&P3).And().Not();
+ *
+ * Equivalent infix expression: !((P1 || P2) && P3)
+ * Assume predicate results of: P1 = 0, P2 = 1, P3 = 0
+ * Expression stack prior to evaluation: P1 P2 OR P3 AND NOT
+ * Evaluation step 1: 1 P3 AND NOT (evaluated P1 P2 OR)
+ * Evaluation step 2: 0 NOT (evaluated 1 P3 AND)
+ * Evaluation step 3: 1 (evaluated 0 NOT; final result)
+ * @endverbatim
+ */
+ virtual bool operator()(
+ const Target* i_pTarget) const;
+
+ private:
+
+ /**
+ * @brief Enumeration describing the type of logical operator to
+ * apply to one or more previous predicate evaluations
+ */
+ enum LogicalOperator
+ {
+ EVAL, ///< Special logical operator - evaluate a predicate
+ AND, ///< Logically AND the result of the preceding two evaluations
+ OR, ///< Logically OR the result of the preceding two evaluations
+ NOT, ///< Logically negate the result of the preceding evaluation
+ };
+
+ /**
+ * @brief Structure describing one unit of the postfix predicate
+ * expression under evaluation
+ */
+ struct Operation
+ {
+ LogicalOperator logicalOp; ///< Logical operator to
+ ///< apply to result stack
+ const PredicateBase* const pPredicate; ///< Predicate to evaluate,
+ ///< if logicalOp == EVAL
+ };
+
+ std::vector<Operation> iv_ops; ///< Expression operations to perform
+
+ TARG_DISABLE_COPY_AND_ASSIGNMENT_OPERATORS(PredicatePostfixExpr);
+};
+
+#undef TARG_CLASS
+#undef TARG_NAMESPACE
+
+} // End namespace TARGETING
+
+#endif // TARG_PREDICATEPOSTFIXEXPR_H
diff --git a/src/include/usr/targeting/targetservice.H b/src/include/usr/targeting/targetservice.H
index 2797890c5..77e4b23f4 100644
--- a/src/include/usr/targeting/targetservice.H
+++ b/src/include/usr/targeting/targetservice.H
@@ -28,6 +28,8 @@
#include <targeting/attributeenums.H>
#include <targeting/target.H>
#include <targeting/entitypath.H>
+#include <targeting/iterators/targetiterator.H>
+#include <targeting/predicates/predicatebase.H>
//******************************************************************************
// Interface Definitions
@@ -140,6 +142,52 @@ class TargetService
void init();
/**
+ * @brief Map iterator types to common aliases
+ */
+ typedef TargetIterator iterator;
+ typedef ConstTargetIterator const_iterator;
+
+ /**
+ * @brief Return iterator which points to first target service target
+ * (or end() if none)
+ *
+ * @return Iterator pointing to first target service target
+ */
+ iterator begin();
+
+ /**
+ * @brief Return iterator to const which points to first target service
+ * target (or end() if none)
+ *
+ * @return Iterator to const pointing to first target service target
+ */
+ const_iterator begin() const;
+
+ /**
+ * @brief Return iterator which points to the "past the end of the
+ * list" target maintained by the target service
+ *
+ * @return Iterator pointing to the "past the end of the list" target
+ * maintained by the target service
+ */
+ iterator end();
+
+ /**
+ * @brief Return iterator to const which points to the "past the end of
+ * the list" target maintained by the target service
+ *
+ * @return Iterator to const pointing to the "past the end of the list"
+ * target maintained by the target service
+ */
+ const_iterator end() const;
+
+ /**
+ * @brief Allow iterator access to the target service's target store
+ */
+ friend class _TargetIterator<Target*>;
+ friend class _TargetIterator<const Target*>;
+
+ /**
* @brief Returns the top level physical target
*
* Returns the top level (usually system) target. Caller must check
@@ -272,25 +320,31 @@ class TargetService
* for said source target, the routine will return all targets
* contained within the processor chip.
*
+ * @param[out] o_list List of target handles that match the specified
+ * criteria
* @param[in] i_pTarget Target from which to search for other targets
* @param[in] i_type Type of association linking the specified target
* to candidate result targets
* @param[in] i_recursionLevel Whether to return candidate targets
* immediately associated to the specified target or recursively
* associated to it.
- * @param[out] o_list List of target handles that match the specified
- * criteria
+ * @param[in] i_pPredicate Pointer to a predicate to be evaluated
+ * against each candidate target (as determined by the source
+ * target, type, and recursion level parameters). If the predicate
+ * returns true, the target will be added to the result list. A
+ * value of NULL acts as a predicate that always returns true.
*
* @pre N/A
*
* @post Caller's list cleared; list of target handles matching the
* specified criteria returned
*/
- void getAssociated(
- const Target* i_pTarget,
- ASSOCIATION_TYPE i_type,
- RECURSION_LEVEL i_recursionLevel,
- TargetHandleList& o_list) const;
+ void getAssociated(
+ TargetHandleList& o_list,
+ const Target* const i_pTarget,
+ const ASSOCIATION_TYPE i_type = CHILD,
+ const RECURSION_LEVEL i_recursionLevel = IMMEDIATE,
+ const PredicateBase* i_pPredicate = NULL) const;
/**
* @brief Dump the target service for debug only
@@ -387,6 +441,10 @@ class TargetService
* @param[in] i_recursionLevel Whether to provide immediate or
* recursive results
* @param[in] i_entityPath Entity path to start search from
+ * @param[in] i_pPredicate Pointer to a predicate to be evaluated
+ * against each candidate target. If the predicate returns true,
+ * the target will be added to the result list. A value of NULL
+ * acts as a predicate that always returns true.
* @param[out] o_list List of returned target handles
*
* @pre Target service must be initialized
@@ -396,10 +454,11 @@ class TargetService
* path returned
*/
void _getInwards(
- ATTRIBUTE_ID i_attr,
- RECURSION_LEVEL i_recursionLevel,
- EntityPath i_entityPath,
- TargetHandleList& o_list) const;
+ ATTRIBUTE_ID i_attr,
+ RECURSION_LEVEL i_recursionLevel,
+ EntityPath i_entityPath,
+ const PredicateBase* i_pPredicate,
+ TargetHandleList& o_list) const;
/**
* @brief Returns handles to the targets associated to the
@@ -418,6 +477,10 @@ class TargetService
* @param[in] i_recursionLevel Whether to provide immediate or
* recursive results
* @param[in] i_entityPath Entity path to look from
+ * @param[in] i_pPredicate Pointer to a predicate to be evaluated
+ * against each candidate target. If the predicate returns true,
+ * the target will be added to the result list. A value of NULL
+ * acts as a predicate that always returns true.
* @param[out] o_list List of returned target handles
*
* @pre Target service must be initialized
@@ -427,13 +490,13 @@ class TargetService
* entity path returned.
*/
void _getOutwards(
- ATTRIBUTE_ID i_attr,
- RECURSION_LEVEL i_recursionLevel,
- EntityPath i_entityPath,
- TargetHandleList& o_list ) const;
+ ATTRIBUTE_ID i_attr,
+ RECURSION_LEVEL i_recursionLevel,
+ EntityPath i_entityPath,
+ const PredicateBase* i_pPredicate,
+ TargetHandleList& o_list ) const;
// Instance variables
-
bool iv_initialized; ///< Is service initialized or not
Target (*iv_targets)[]; ///< Pointer to array of target objects
uint32_t iv_maxTargets; ///< Maximum # target objects in the array
diff --git a/src/usr/targeting/iterators/rangefilter.C b/src/usr/targeting/iterators/rangefilter.C
new file mode 100644
index 000000000..64ceb1f78
--- /dev/null
+++ b/src/usr/targeting/iterators/rangefilter.C
@@ -0,0 +1,89 @@
+
+/**
+ * @file rangefilter.C
+ *
+ * @brief Implementation of an object which takes an iterator range and
+ * allows caller to iterate through the elements which match a supplied
+ * predicate (filter)
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+
+// STD
+
+// Other Host Boot Components
+
+// Targeting Component
+#include <targeting/iterators/rangefilter.H>
+
+//******************************************************************************
+// Macros
+//******************************************************************************
+
+#undef TARG_NAMESPACE
+#undef TARG_CLASS
+#undef TARG_FUNC
+
+//******************************************************************************
+// Implementation
+//******************************************************************************
+
+namespace TARGETING
+{
+
+#define TARG_NAMESPACE "TARGETING::"
+
+#define TARG_CLASS "RangeFilter<IteratorType>::"
+
+//******************************************************************************
+// RangeFilter<IteratorType>::advance
+//******************************************************************************
+
+template<typename IteratorType>
+void RangeFilter<IteratorType>::advance()
+{
+ if(iv_current != iv_end)
+ {
+ while( (++iv_current) != iv_end )
+ {
+ if( (!iv_pPredicate)
+ || ((*iv_pPredicate)(*iv_current)))
+ {
+ break;
+ }
+ }
+ }
+}
+
+//******************************************************************************
+// RangeFilter<IteratorType>::advanceIfNoMatch
+//******************************************************************************
+
+template<typename IteratorType>
+void RangeFilter<IteratorType>::advanceIfNoMatch()
+{
+ if( (iv_current != iv_end)
+ && ( (iv_pPredicate)
+ && (!((*iv_pPredicate)(*iv_current)))))
+ {
+ advance();
+ }
+}
+
+//******************************************************************************
+// Explicit template class member function instantiations
+//******************************************************************************
+
+template void RangeFilter<TargetIterator>::advance();
+template void RangeFilter<ConstTargetIterator>::advance();
+
+template void RangeFilter<TargetIterator>::advanceIfNoMatch();
+template void RangeFilter<ConstTargetIterator>::advanceIfNoMatch();
+
+#undef TARG_CLASS
+#undef TARG_NAMESPACE
+
+} // End namespace TARGETING
+
diff --git a/src/usr/targeting/iterators/targetiterator.C b/src/usr/targeting/iterators/targetiterator.C
new file mode 100644
index 000000000..f3549a633
--- /dev/null
+++ b/src/usr/targeting/iterators/targetiterator.C
@@ -0,0 +1,88 @@
+
+/**
+ * @file targetiterator.C
+ *
+ * @brief Implementation of iterator/const iterator used to iterate through
+ * target service targets
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+
+// STD
+
+// Other Host Boot Components
+
+// Targeting Component
+#include <targeting/iterators/targetiterator.H>
+#include <targeting/targetservice.H>
+
+//******************************************************************************
+// Macros
+//******************************************************************************
+
+#undef TARG_NAMESPACE
+#undef TARG_CLASS
+#undef TARG_FUNC
+
+//******************************************************************************
+// Implementation
+//******************************************************************************
+
+namespace TARGETING
+{
+
+#define TARG_NAMESPACE "TARGETING::"
+
+#define TARG_CLASS "_TargetIterator<T>::"
+
+//******************************************************************************
+// TargetIterator::advance
+//******************************************************************************
+
+template<typename T>
+void _TargetIterator<T>::advance()
+{
+ TargetService& l_targetService = targetService();
+
+ // If cursor points to end()/NULL, do nothing. Otherwise, check to see if
+ // it should advance (possibly to NULL)
+ if(iv_pCurrent != NULL)
+ {
+ // Advance to end() if no targets available. Otherwise, check to see if
+ // it should advance (possibly to NULL)
+ if (l_targetService.iv_maxTargets > 0)
+ {
+ // If at or past last element, advance to end() else advance
+ if(iv_pCurrent >=
+ &(*l_targetService.iv_targets)[l_targetService.iv_maxTargets-1])
+ {
+ iv_pCurrent = NULL;
+ }
+ else
+ {
+ iv_pCurrent++;
+ }
+ }
+ else
+ {
+ iv_pCurrent = NULL;
+ }
+ }
+}
+
+//******************************************************************************
+// Explicit template class member function instantiations
+//******************************************************************************
+
+template void _TargetIterator<Target*>::advance();
+template void _TargetIterator<const Target*>::advance();
+
+#undef TARG_CLASS
+#undef TARG_NAMESPACE
+
+} // End namespace TARGETING
+
+
+
diff --git a/src/usr/targeting/makefile b/src/usr/targeting/makefile
index 09b9d3be3..70edd18ac 100644
--- a/src/usr/targeting/makefile
+++ b/src/usr/targeting/makefile
@@ -1,7 +1,26 @@
ROOTPATH = ../../..
MODULE = targeting
-OBJS = target.o targetservice.o entitypath.o fakepnordata.o
+VPATH = \
+ predicates: \
+ iterators:
+
+PREDICATES_OBJS = \
+ predicatebase.o \
+ predicatepostfixexpr.o \
+ predicatectm.o
+
+ITERATORS_OBJS = \
+ targetiterator.o \
+ rangefilter.o
+
+TARGET_OBJS = \
+ target.o \
+ targetservice.o \
+ entitypath.o \
+ fakepnordata.o
+
+OBJS = ${TARGET_OBJS} ${PREDICATES_OBJS} ${ITERATORS_OBJS}
SUBDIRS = test.d
diff --git a/src/usr/targeting/predicates/predicatebase.C b/src/usr/targeting/predicates/predicatebase.C
new file mode 100644
index 000000000..61e17b984
--- /dev/null
+++ b/src/usr/targeting/predicates/predicatebase.C
@@ -0,0 +1,54 @@
+
+/**
+ * @file predicatebase.C
+ *
+ * @brief Implementation for an abstract targeting predicate which filters a
+ * set of targets based on the programmed criteria. Only required to
+ * implement the virtual destrutor which leads to duplicate weak symbols
+ * if it were instead inlined.
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+
+// STD
+
+// Other Host Boot Components
+
+// Targeting Component
+#include <targeting/predicates/predicatebase.H>
+
+//******************************************************************************
+// Macros
+//******************************************************************************
+
+#undef TARG_NAMESPACE
+#undef TARG_CLASS
+#undef TARG_FN
+
+//******************************************************************************
+// Interface
+//******************************************************************************
+
+namespace TARGETING
+{
+
+#define TARG_NAMESPACE "TARGETING::"
+#define TARG_CLASS "PredicateBase::"
+
+//******************************************************************************
+// PredicateBase::~PredicateBase
+//******************************************************************************
+
+PredicateBase::~PredicateBase()
+{
+ #define TARG_FN "~PredicateBase()"
+ #undef TARG_FN
+}
+
+#undef TARG_CLASS
+#undef TARG_NAMESPACE
+
+} // End namespace TARGETING
+
diff --git a/src/usr/targeting/predicates/predicatectm.C b/src/usr/targeting/predicates/predicatectm.C
new file mode 100644
index 000000000..8185020f5
--- /dev/null
+++ b/src/usr/targeting/predicates/predicatectm.C
@@ -0,0 +1,63 @@
+
+/**
+ * @file predicatectm.C
+ *
+ * @brief Implementation for a predicate which fiters a target based on its
+ * class, type, and model.
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+
+// STD
+
+// Other Host Boot Components
+
+// Targeting Component
+#include <targeting/target.H>
+#include <targeting/attributeenums.H>
+#include <targeting/predicates/predicatectm.H>
+
+//******************************************************************************
+// Macros
+//******************************************************************************
+
+#undef TARG_NAMESPACE
+#undef TARG_CLASS
+#undef TARG_FN
+
+//******************************************************************************
+// Interface
+//******************************************************************************
+
+namespace TARGETING
+{
+
+#define TARG_NAMESPACE "TARGETING::"
+#define TARG_CLASS "PredicateCTM::"
+
+//******************************************************************************
+// PredicateCTM::operator()
+//******************************************************************************
+
+bool PredicateCTM::operator()(
+ const Target* const i_pTarget) const
+{
+ #define TARG_FUNC "operator()(...)"
+
+ return ( ( (iv_class == CLASS_NA)
+ || (i_pTarget->getAttr<ATTR_CLASS>() == iv_class))
+ && ( (iv_type == TYPE_NA)
+ || (i_pTarget->getAttr<ATTR_TYPE>() == iv_type))
+ && ( (iv_model == MODEL_NA)
+ || (i_pTarget->getAttr<ATTR_MODEL>() == iv_model)));
+
+ #undef TARG_FUNC
+}
+
+#undef TARG_CLASS
+#undef TARG_NAMESPACE
+
+} // End namespace TARGETING
+
diff --git a/src/usr/targeting/predicates/predicatepostfixexpr.C b/src/usr/targeting/predicates/predicatepostfixexpr.C
new file mode 100644
index 000000000..7f5e89260
--- /dev/null
+++ b/src/usr/targeting/predicates/predicatepostfixexpr.C
@@ -0,0 +1,198 @@
+
+/**
+ * @file predicatepostfixexpr.C
+ *
+ * @brief Implementation for predicate which allows callers to chain multiple
+ * other predicates together in complex logical expressions, and then
+ * evaluate them against a target
+ */
+
+//******************************************************************************
+// Includes
+//******************************************************************************
+
+// STD
+
+// Other Host Boot Components
+#include <assert.h>
+
+// Targeting Component
+#include <targeting/predicates/predicatepostfixexpr.H>
+#include "../trace.H"
+
+//******************************************************************************
+// Macros
+//******************************************************************************
+
+#undef TARG_NAMESPACE
+#undef TARG_CLASS
+#undef TARG_FN
+
+//******************************************************************************
+// Interface
+//******************************************************************************
+
+namespace TARGETING
+{
+
+#define TARG_NAMESPACE "TARGETING::"
+#define TARG_CLASS "PredicatePostfixExpr::"
+
+//******************************************************************************
+// PredicatePostfixExpr::PredicatePostfixExpr
+//******************************************************************************
+
+PredicatePostfixExpr::PredicatePostfixExpr()
+{
+}
+
+//******************************************************************************
+// PredicatePostfixExpr::~PredicatePostfixExpr
+//******************************************************************************
+
+PredicatePostfixExpr::~PredicatePostfixExpr()
+{
+}
+
+//******************************************************************************
+// PredicatePostfixExpr::push
+//******************************************************************************
+
+PredicatePostfixExpr& PredicatePostfixExpr::push(
+ const PredicateBase* const i_pPredicate)
+{
+ #define TARG_FN "push(...)"
+
+ assert(i_pPredicate != NULL,
+ TARG_LOC "Caller supplied a NULL predicate");
+ Operation l_op = {EVAL,i_pPredicate};
+ iv_ops.push_back(l_op);
+ return *this;
+
+ #undef TARG_FN
+}
+
+//******************************************************************************
+// PredicatePostfixExpr::And
+//******************************************************************************
+
+PredicatePostfixExpr& PredicatePostfixExpr::And()
+{
+ #define TARG_FN "And()"
+
+ Operation l_op = {AND,NULL};
+ iv_ops.push_back(l_op);
+ return *this;
+
+ #undef TARG_FN
+}
+
+//******************************************************************************
+// PredicatePostfixExpr::Not
+//******************************************************************************
+
+PredicatePostfixExpr& PredicatePostfixExpr::Not()
+{
+ #define TARG_FN "Not()"
+
+ Operation l_op = {NOT,NULL};
+ iv_ops.push_back(l_op);
+ return *this;
+
+ #undef TARG_FN
+}
+
+//******************************************************************************
+// PredicatePostfixExpr::Or
+//******************************************************************************
+
+PredicatePostfixExpr& PredicatePostfixExpr::Or()
+{
+ #define TARG_FN "Or()"
+
+ Operation l_op = {OR,NULL};
+ iv_ops.push_back(l_op);
+ return *this;
+
+ #undef TARG_FN
+}
+
+//******************************************************************************
+// PredicatePostfixExpr::operator()
+//******************************************************************************
+
+bool PredicatePostfixExpr::operator()(
+ const Target* const i_pTarget) const
+{
+ #define TARG_FN "operator()(...)"
+
+ assert(i_pTarget != NULL,
+ TARG_LOC "Caller supplied a NULL target");
+
+ std::vector<bool> l_stack;
+ bool l_result = false;
+
+ for(uint32_t i=0; i<iv_ops.size(); ++i)
+ {
+ switch(iv_ops[i].logicalOp)
+ {
+ case EVAL:
+ l_stack.push_back((*iv_ops[i].pPredicate)(i_pTarget));
+ break;
+ case AND:
+ assert(l_stack.size() >= 2,
+ TARG_LOC "Stack for AND must be >=2 but is %d",
+ l_stack.size());
+ l_result = l_stack.back();
+ l_stack.pop_back();
+ l_stack.back() &= l_result;
+ break;
+ case OR:
+ assert(l_stack.size() >= 2,
+ TARG_LOC "Stack for OR must be >= 2 but is %d",
+ l_stack.size());
+ l_result = l_stack.back();
+ l_stack.pop_back();
+ l_stack.back() |= l_result;
+ break;
+ case NOT:
+ assert(l_stack.size() >= 1,
+ TARG_LOC "Stack for NOT must be >= 1 but is %d",
+ l_stack.size());
+ l_stack.back() = !l_stack.back();
+ break;
+ default:
+ assert(0,
+ TARG_LOC "Attempted to evaluate unsupported "
+ "logical operation %d",
+ iv_ops[i].logicalOp);
+ break;
+ }
+ }
+
+ // If no predicates and we haven't asserted (no misformatting), element
+ // should be returned
+ if(l_stack.size() == 0)
+ {
+ l_result = true;
+ }
+ else
+ {
+ assert(l_stack.size() == 1,
+ TARG_LOC "Postfix expression created incorrectly. Stack "
+ "size should be 1 but is %d",
+ l_stack.size());
+
+ l_result = l_stack.front();
+ }
+
+ return l_result;
+
+ #undef TARG_FN
+}
+
+#undef TARG_CLASS
+#undef TARG_NAMESPACE
+
+} // End namespace TARGETING
+
diff --git a/src/usr/targeting/targetservice.C b/src/usr/targeting/targetservice.C
index 4418358ef..3b3b4098b 100644
--- a/src/usr/targeting/targetservice.C
+++ b/src/usr/targeting/targetservice.C
@@ -23,6 +23,7 @@
#include <targeting/targetservice.H>
#include "trace.H"
#include "fakepnordata.H"
+#include <targeting/predicates/predicatebase.H>
//******************************************************************************
// targetService
@@ -162,6 +163,72 @@ void TargetService::init()
}
//******************************************************************************
+// TargetService::begin (non-const version)
+//******************************************************************************
+
+TargetService::iterator TargetService::begin()
+{
+ #define TARG_FN "begin()"
+
+ assert(iv_initialized);
+
+ Target* l_pFirstTarget = (iv_maxTargets == 0) ? NULL : &(*iv_targets)[0];
+
+ return iterator(l_pFirstTarget);
+
+ #undef TARG_FN
+}
+
+//******************************************************************************
+// TargetService::begin (const version)
+//******************************************************************************
+
+//TargetService::const_iterator
+_TargetIterator<const Target*> TargetService::begin() const
+{
+ #define TARG_FN "begin() const"
+
+ assert(iv_initialized);
+
+ const Target* l_pFirstTarget =
+ (iv_maxTargets == 0) ? NULL : &(*iv_targets)[0];
+
+ return const_iterator(l_pFirstTarget);
+
+ #undef TARG_FN
+}
+
+//******************************************************************************
+// TargetService::end (non-const version)
+//******************************************************************************
+
+TargetService::iterator TargetService::end()
+{
+ #define TARG_FN "end()"
+
+ assert(iv_initialized);
+
+ return iterator(NULL);
+
+ #undef TARG_FN
+}
+
+//******************************************************************************
+// TargetService::end (const version)
+//******************************************************************************
+
+TargetService::const_iterator TargetService::end() const
+{
+ #define TARG_FN "end() const"
+
+ assert(iv_initialized);
+
+ return const_iterator(NULL);
+
+ #undef TARG_FN
+}
+
+//******************************************************************************
// TargetService::getTopLevelTarget
//******************************************************************************
@@ -305,10 +372,11 @@ bool TargetService::tryGetPath(
//******************************************************************************
void TargetService::getAssociated(
- const Target* const i_pTarget,
- const ASSOCIATION_TYPE i_type,
- const RECURSION_LEVEL i_recursionLevel,
- TargetHandleList& o_list) const
+ TargetHandleList& o_list,
+ const Target* const i_pTarget,
+ const ASSOCIATION_TYPE i_type,
+ const RECURSION_LEVEL i_recursionLevel,
+ const PredicateBase* const i_pPredicate) const
{
#define TARG_FN "getAssociated(...)"
@@ -340,13 +408,13 @@ void TargetService::getAssociated(
if (iv_associationMappings[i].associationDir == INWARDS)
{
(void) _getInwards(iv_associationMappings[i].attr,
- i_recursionLevel, l_entityPath, o_list);
+ i_recursionLevel, l_entityPath, i_pPredicate, o_list);
}
else if (iv_associationMappings[i].associationDir
== OUTWARDS)
{
(void) _getOutwards(iv_associationMappings[i].attr,
- i_recursionLevel, l_entityPath, o_list);
+ i_recursionLevel, l_entityPath, i_pPredicate, o_list);
}
else
{
@@ -509,10 +577,11 @@ uint32_t TargetService::_maxTargets()
//******************************************************************************
void TargetService::_getInwards(
- const ATTRIBUTE_ID i_attr,
- const RECURSION_LEVEL i_recursionLevel,
- EntityPath i_entityPath,
- TargetHandleList& o_list) const
+ const ATTRIBUTE_ID i_attr,
+ const RECURSION_LEVEL i_recursionLevel,
+ EntityPath i_entityPath,
+ const PredicateBase* const i_pPredicate,
+ TargetHandleList& o_list) const
{
#define TARG_FN "_getInwards(...)"
@@ -524,7 +593,10 @@ void TargetService::_getInwards(
EntityPath l_candidatePath;
bool l_candidateFound = tryGetPath(i_attr, &(*iv_targets)[i],
l_candidatePath);
- if (l_candidateFound && (l_candidatePath == i_entityPath))
+ if ( l_candidateFound
+ && (l_candidatePath == i_entityPath)
+ && ( (i_pPredicate == NULL)
+ || (*i_pPredicate)( &(*iv_targets)[i]) ) )
{
o_list.push_back(&(*iv_targets)[i]);
break;
@@ -545,10 +617,11 @@ void TargetService::_getInwards(
//******************************************************************************
void TargetService::_getOutwards(
- const ATTRIBUTE_ID i_attr,
- const RECURSION_LEVEL i_recursionLevel,
- EntityPath i_entityPath,
- TargetHandleList& o_list) const
+ const ATTRIBUTE_ID i_attr,
+ const RECURSION_LEVEL i_recursionLevel,
+ EntityPath i_entityPath,
+ const PredicateBase* const i_pPredicate,
+ TargetHandleList& o_list) const
{
#define TARG_FN "_getOutwards()...)"
@@ -573,7 +646,9 @@ void TargetService::_getOutwards(
|| ( (i_recursionLevel == ALL)
&& (l_candidatePath.size() > i_entityPath.size())))
{
- if (i_entityPath.equals(l_candidatePath,i_entityPath.size()))
+ if ( i_entityPath.equals(l_candidatePath,i_entityPath.size())
+ && ( (i_pPredicate == NULL)
+ || (*i_pPredicate)( &(*iv_targets)[i]) ) )
{
o_list.push_back(&(*iv_targets)[i]);
}
@@ -591,3 +666,4 @@ void TargetService::_getOutwards(
#undef TARG_NAMESPACE
} // End namespace TARGETING
+
diff --git a/src/usr/targeting/test/targetingtest.H b/src/usr/targeting/test/targetingtest.H
index bd8ffdb0e..309bf3606 100644
--- a/src/usr/targeting/test/targetingtest.H
+++ b/src/usr/targeting/test/targetingtest.H
@@ -23,6 +23,9 @@
#include <targeting/entitypath.H>
#include <targeting/target.H>
#include <targeting/targetservice.H>
+#include <targeting/iterators/rangefilter.H>
+#include <targeting/predicates/predicatectm.H>
+#include <targeting/predicates/predicatepostfixexpr.H>
class TargetingTestSuite: public CxxTest::TestSuite
{
@@ -128,9 +131,11 @@ class TargetingTestSuite: public CxxTest::TestSuite
// TargetHandleList& o_list) const;
TargetHandleList l_list;
- (void) l_targetService.getAssociated(l_pTopLevel,
+ (void) l_targetService.getAssociated(
+ l_list,
+ l_pTopLevel,
TARGETING::TargetService::CHILD,
- TARGETING::TargetService::IMMEDIATE, l_list);
+ TARGETING::TargetService::IMMEDIATE);
if (!l_list.size())
{
TS_FAIL("Should have found some child elements" );
@@ -140,9 +145,11 @@ class TargetingTestSuite: public CxxTest::TestSuite
// target
TargetHandleList l_parentList;
- (void) l_targetService.getAssociated(l_list[0],
+ (void) l_targetService.getAssociated(
+ l_parentList,
+ l_list[0],
TARGETING::TargetService::PARENT,
- TARGETING::TargetService::IMMEDIATE, l_parentList);
+ TARGETING::TargetService::IMMEDIATE);
if (l_parentList.size() != 1)
{
@@ -155,18 +162,22 @@ class TargetingTestSuite: public CxxTest::TestSuite
"handle" );
}
- (void) l_targetService.getAssociated(l_pTopLevel,
+ (void) l_targetService.getAssociated(
+ l_list,
+ l_pTopLevel,
TARGETING::TargetService::CHILD_BY_AFFINITY,
- TARGETING::TargetService::IMMEDIATE, l_list);
+ TARGETING::TargetService::IMMEDIATE);
if (!l_list.size())
{
TS_FAIL("Should have found some child elements" );
}
- (void) l_targetService.getAssociated(l_pTopLevel,
+ (void) l_targetService.getAssociated(
+ l_list,
+ l_pTopLevel,
TARGETING::TargetService::CHILD_BY_AFFINITY,
- TARGETING::TargetService::ALL, l_list);
+ TARGETING::TargetService::ALL);
if (!l_list.size())
{
@@ -452,6 +463,512 @@ class TargetingTestSuite: public CxxTest::TestSuite
TS_TRACE(EXIT_MRK "testTargetClass" );
}
+
+ void testPredicateCtm()
+ {
+ TS_TRACE(ENTER_MRK "testPredicateCtm" );
+
+ using namespace TARGETING;
+ TargetService& l_targetService = targetService();
+
+ // Get top level (system) target
+ Target* l_pTopLevel = NULL;
+ (void) l_targetService.getTopLevelTarget(l_pTopLevel);
+ if (l_pTopLevel == NULL)
+ {
+ TS_FAIL("Top level handle was NULL when initialization "
+ "complete");
+ }
+
+ PredicateCTM l_allWild;
+ if( ! l_allWild(l_pTopLevel) )
+ {
+ TS_FAIL("CTM all wildcards filter should have matched system "
+ "target");
+ }
+
+ PredicateCTM l_typeModelWild(CLASS_SYS);
+ if( ! l_typeModelWild(l_pTopLevel) )
+ {
+ TS_FAIL("CTM class sys, remaining wildcards filter should have "
+ "matched system ");
+ }
+
+ PredicateCTM l_modelWild(CLASS_SYS,TYPE_SYS);
+ if( ! l_modelWild(l_pTopLevel) )
+ {
+ TS_FAIL("CTM class sys, type sys, remaining wildcards filter "
+ "should have matched system ");
+ }
+
+ PredicateCTM l_noWild(CLASS_SYS,TYPE_SYS,MODEL_POWER8);
+ if( ! l_noWild(l_pTopLevel) )
+ {
+ TS_FAIL("CTM class sys, type sys, model power8 should have "
+ "matched system ");
+ }
+
+ PredicateCTM l_classWild(CLASS_NA,TYPE_SYS,MODEL_POWER8);
+ if( ! l_classWild(l_pTopLevel) )
+ {
+ TS_FAIL("CTM class wild, type sys, model power8 should have "
+ "matched system ");
+ }
+
+ PredicateCTM l_typeWild(CLASS_SYS,TYPE_NA,MODEL_POWER8);
+ if( ! l_typeWild(l_pTopLevel) )
+ {
+ TS_FAIL("CTM class sys, wild, model power8 should have "
+ "matched system ");
+ }
+
+ PredicateCTM l_classModelWild(CLASS_NA,TYPE_SYS,MODEL_NA);
+ if( ! l_classModelWild(l_pTopLevel) )
+ {
+ TS_FAIL("CTM wild, type sys, wild should have "
+ "matched system ");
+ }
+
+ PredicateCTM l_classTypeWild(CLASS_NA,TYPE_NA,MODEL_NA);
+ if( ! l_classTypeWild(l_pTopLevel) )
+ {
+ TS_FAIL("CTM wild, wild, model should have "
+ "matched system ");
+ }
+
+ PredicateCTM l_chipClass(CLASS_CHIP,TYPE_NA,MODEL_NA);
+ if( l_chipClass(l_pTopLevel) )
+ {
+ TS_FAIL("CTM of class chip, wild, wild should not have matched "
+ "matched system ");
+ }
+
+ #if 0 // Prove copy CTOR/assignment operator is disabled
+ PredicateCTM l_ctmLhs;
+ PredicateCTM l_ctmRhs;
+
+ l_ctmLhs = l_ctmRhs;
+
+ PredicateCTM l_ctmCtor(l_ctmRhs);
+ #endif
+
+ PredicateBase* l_pBase = new PredicateCTM(CLASS_SYS);
+ delete l_pBase;
+ l_pBase = NULL;
+
+ TS_TRACE(EXIT_MRK "testPredicateCtm" );
+
+ }
+
+ void testPredicatePostfixExpr()
+ {
+ TS_TRACE(ENTER_MRK "testPredicatePostfixExpr" );
+
+ using namespace TARGETING;
+ TargetService& l_targetService = targetService();
+
+ // Get top level (system) target
+ Target* l_pTopLevel = NULL;
+ (void) l_targetService.getTopLevelTarget(l_pTopLevel);
+ if (l_pTopLevel == NULL)
+ {
+ TS_FAIL("Top level handle was NULL when initialization "
+ "complete");
+ }
+
+ PredicatePostfixExpr l_alwaysTrueExpr;
+ if(!l_alwaysTrueExpr(l_pTopLevel) )
+ {
+ TS_FAIL("Always true filter should have matched system");
+ }
+
+ #if 0
+ // Triggers NULL assertion check on push
+ l_alwaysTrueExpr.push(NULL);
+ #endif
+
+ #if 0
+ // Triggers not enough stack elements assertion when evaluating Not
+ l_alwaysTrueExpr.Not();
+ if(l_alwaysTrueExpr(l_pTopLevel) )
+ {
+ TS_FAIL("Negated always true filter should not have matched "
+ "system");
+ }
+ #endif
+
+ #if 0
+ // Triggers illegal target assertion
+ l_alwaysTrueExpr(NULL);
+ #endif
+
+ #if 0
+ // Triggers formatting assertion
+ l_alwaysTrueExpr.And();
+ l_alwaysTrueExpr(l_pTopLevel);
+ #endif
+
+ #if 0
+ // Triggers formatting assertion
+ l_alwaysTrueExpr.Or();
+ l_alwaysTrueExpr(l_pTopLevel);
+ #endif
+
+ PredicateCTM l_sysClass(CLASS_SYS);
+
+ #if 0
+ // Triggers formatting assertion
+ l_alwaysTrueExpr.push(&l_sysClass);
+ l_alwaysTrueExpr.And();
+ l_alwaysTrueExpr(l_pTopLevel);
+ #endif
+
+ #if 0
+ // Triggers formatting assertion
+ l_alwaysTrueExpr.push(&l_sysClass);
+ l_alwaysTrueExpr.Or();
+ l_alwaysTrueExpr(l_pTopLevel);
+ #endif
+
+ #if 0
+ // Triggers illegal formatting exception
+ // != 1 results on stack
+ l_alwaysTrueExpr.push(&l_sysClass);
+ l_alwaysTrueExpr.push(&l_sysClass);
+ l_alwaysTrueExpr.Not();
+ l_alwaysTrueExpr(l_pTopLevel);
+ #endif
+
+ PredicateCTM l_sysType(CLASS_NA,TYPE_SYS);
+ PredicateCTM l_power8Model(CLASS_NA,TYPE_NA,MODEL_POWER8);
+ PredicatePostfixExpr l_expr;
+ l_expr.push(&l_sysClass).push(&l_sysType).And();
+ l_expr.push(&l_power8Model).And();
+
+ if(!l_expr(l_pTopLevel) )
+ {
+ TS_FAIL("CTM of class sys && type sys && model power8 should "
+ "have matched system");
+ }
+
+ l_expr.Not();
+
+ if(l_expr(l_pTopLevel) )
+ {
+ TS_FAIL("CTM of class sys && type sys && model power8 should "
+ "npt have matched system after negation");
+ }
+
+ l_expr.push(&l_sysClass);
+ l_expr.Or();
+
+ if(!l_expr(l_pTopLevel) )
+ {
+ TS_FAIL("CTM of class sys && type sys && model power8 should "
+ "have matched system after negation then || sys class");
+ }
+
+ PredicatePostfixExpr* l_pExpr = new PredicatePostfixExpr;
+ l_pExpr->push(&l_sysClass).push(&l_sysType).And();
+ l_pExpr->push(&l_power8Model).And();
+ delete (static_cast<PredicateBase*>(l_pExpr));
+
+ #if 0
+ PredicatePostfixExpr l_lhs;
+ PredicatePostfixExpr l_rhs;
+
+ l_lhs = l_rhs;
+
+ PredicatePostfixExpr l_cpCtor(l_rhs);
+ #endif
+
+
+ TS_TRACE(EXIT_MRK "testPredicatePostfixExpr" );
+ }
+
+ void testTargetIterator()
+ {
+ TS_TRACE(ENTER_MRK "testTargetIterator");
+
+ using namespace TARGETING;
+ TargetService& l_targetService = targetService();
+
+
+ TargetIterator l_pIt;
+ if( l_pIt != l_targetService.end() )
+ {
+ TS_FAIL("Default TargetIterator should point to past the end "
+ "of container");
+ }
+
+ ++l_pIt;
+ if( l_pIt != l_targetService.end() )
+ {
+ TS_FAIL("Default TargetIterator preincremented should point to "
+ "past the end of container");
+ }
+
+ TargetIterator* l_pItNew = new TargetIterator;
+ delete l_pItNew;
+ l_pItNew = NULL;
+
+ if(*l_pIt != NULL)
+ {
+ TS_FAIL("Default TargetIterator dereference should return NULL");
+ }
+
+ // Get top level (system) target to verify at least 1 target
+ Target* l_pTopLevel = NULL;
+ (void) l_targetService.getTopLevelTarget(l_pTopLevel);
+ if (l_pTopLevel == NULL)
+ {
+ TS_FAIL("Top level handle was NULL when initialization "
+ "complete");
+ }
+
+ l_pIt = l_targetService.begin();
+ if((*l_pIt) == NULL)
+ {
+ TS_FAIL("TargetService begin() should return !NULL");
+ }
+
+ CLASS l_class = CLASS_NA;
+ if( !l_pIt->tryGetAttr<ATTR_CLASS>(l_class) )
+ {
+ TS_FAIL("Failed to get expected class attribute");
+ }
+
+ TargetIterator l_rhs = l_targetService.begin();
+ if( ! (l_pIt == l_rhs) )
+ {
+ TS_FAIL("Iterators should be equal, but aren't");
+ }
+
+ l_rhs = l_targetService.begin();
+ if( l_pIt != l_rhs )
+ {
+ TS_FAIL("Iterators should be equal, but aren't");
+ }
+
+ TargetIterator l_rhs2 = l_targetService.begin();
+ ++l_rhs2;
+ ++l_pIt;
+ if( l_pIt != l_rhs2 )
+ {
+ TS_FAIL("Iterators should be equal, but aren't");
+ }
+
+ l_rhs2++;
+ l_pIt++;
+ if( l_pIt != l_rhs2 )
+ {
+ TS_FAIL("Iterators should be equal, but aren't");
+ }
+
+ TargetIterator l_pItClone(l_rhs2);
+ if( l_pIt != l_pItClone)
+ {
+ TS_FAIL("Iterators should be equal, but aren't");
+ }
+
+ if(l_pIt != l_pItClone++)
+ {
+ TS_FAIL("Iterators should be equal, but aren't");
+ }
+
+ if( (++l_pIt) != l_pItClone)
+ {
+ TS_FAIL("Iterators should be equal, but aren't");
+ }
+
+ const TargetService& l_constTargetService = targetService();
+
+ ConstTargetIterator l_pConstIt;
+ if( l_pConstIt != l_constTargetService.end() )
+ {
+ TS_FAIL("Default ConstTargetIterator should point to past the "
+ "end of container");
+ }
+
+ l_pConstIt = l_constTargetService.begin();
+ if( (*l_pConstIt) == NULL)
+ {
+ TS_FAIL("Iterator does not point to valid Target as expected");
+ }
+
+ TS_TRACE(EXIT_MRK "testTargetIterator" );
+ }
+
+ void testRangeFilter(void)
+ {
+ TS_TRACE(ENTER_MRK "testRangeFilters" );
+
+ using namespace TARGETING;
+
+ TargetRangeFilter* l_pRangeFilter = new TargetRangeFilter(
+ targetService().begin(),
+ targetService().end(),
+ NULL);
+ delete l_pRangeFilter;
+ l_pRangeFilter = NULL;
+
+
+ TargetRangeFilter l_f1(
+ targetService().begin(),
+ targetService().end(),
+ NULL);
+
+ Target* l_pBegin = (*l_f1);
+ ++l_f1;
+ Target* l_pNext = (*l_f1);
+ if( (l_pBegin == NULL)
+ || (l_pNext == NULL)
+ || (l_pBegin == l_pNext)
+ )
+ {
+ TS_FAIL("Target* pointed to by Begin/next NULL -or- begin =="
+ "next");
+ }
+
+ l_f1.reset();
+ if( *l_f1 != l_pBegin )
+ {
+ TS_FAIL("Target* after reset should be equal to original");
+ }
+
+ l_f1.reset();
+ TargetRangeFilter l_f2 = l_f1;
+ PredicateCTM l_ctm(CLASS_SYS,TYPE_CORE); // Nonsense CTM
+ l_f1.setPredicate(&l_ctm);
+ if( *l_f1 == l_pBegin )
+ {
+ TS_FAIL("Target* after reset and change of predicate should be"
+ "different than the original");
+ }
+
+ PredicateCTM l_ctm1(CLASS_CHIP,TYPE_PROC);
+
+ TargetRangeFilter l_f3(
+ targetService().begin(),
+ targetService().end(),
+ &l_ctm1);
+ for(;l_f3;++l_f3)
+ {
+ if(l_f3->getAttr<ATTR_TYPE>() != TYPE_PROC)
+ {
+ TS_FAIL("Should only have returned type proc");
+ break;
+ }
+ }
+
+ TargetIterator l_pIt = targetService().begin();
+ ++l_pIt;
+ ++l_pIt;
+
+ if(l_pIt == targetService().end())
+ {
+ TS_FAIL("Not enough elements for test");
+ }
+
+ TargetRangeFilter l_partial(
+ targetService().begin(),
+ l_pIt,
+ NULL);
+ int i=0;
+
+ for(; l_partial; ++l_partial)
+ {
+ i++;
+ }
+
+ if(i != 2)
+ {
+ TS_FAIL("Should have gotten 2 elements %d",i);
+ }
+
+ TS_TRACE(EXIT_MRK "testRangeFilter" );
+ }
+
+ void testComplexFilter(void)
+ {
+ TS_TRACE(ENTER_MRK "testComplexFilter" );
+
+ using namespace TARGETING;
+
+ TargetService& l_targetService = targetService();
+
+ TargetRangeFilter f(l_targetService.begin(),
+ l_targetService.end(),
+ NULL);
+ int l_count = 0;
+ for(; f; ++f, l_count++)
+ {
+ }
+
+ TS_TRACE(INF_MRK "Found %d total targets", l_count);
+
+ PredicateCTM l_procs(CLASS_CHIP);
+ PredicateCTM l_enclosures(CLASS_ENC);
+ PredicatePostfixExpr l_query;
+ l_query.push(&l_procs).push(&l_enclosures).Or();
+
+ f.setPredicate(&l_query);
+ f.reset();
+
+ l_count = 0;
+ for(; f; ++f, ++l_count)
+ {
+ EntityPath l_path = f->getAttr<ATTR_PHYS_PATH>();
+ l_path.dump();
+ }
+
+ TS_TRACE(INF_MRK "Found %d targets that are chips or enclosures ",
+ l_count);
+
+ l_query.Not();
+ f.reset();
+
+ l_count = 0;
+ for(; f; ++f, ++l_count)
+ {
+ }
+
+ TS_TRACE(INF_MRK "Found %d targets that are not chips or "
+ "enclosures",l_count);
+
+ Target* l_pMasterProcChipTargetHandle = NULL;
+ (void) l_targetService.masterProcChipTargetHandle(
+ l_pMasterProcChipTargetHandle);
+ if(l_pMasterProcChipTargetHandle == NULL)
+ {
+ TS_FAIL("Master processor chip target not found");
+ }
+
+ PredicateCTM l_ex(CLASS_UNIT,TYPE_EX);
+ PredicateCTM l_mba(CLASS_UNIT,TYPE_MBA);
+ PredicatePostfixExpr l_procquery;
+ l_procquery.push(&l_ex).push(&l_mba).Or();
+
+ TargetHandleList l_list;
+ (void) targetService().getAssociated(
+ l_list,
+ l_pMasterProcChipTargetHandle,
+ TARGETING::TargetService::CHILD,
+ TARGETING::TargetService::ALL,
+ &l_procquery);
+
+ l_count = 0;
+ for(uint32_t i=0; i<l_list.size(); ++i, ++l_count)
+ {
+ EntityPath l_path = l_list[i]->getAttr<ATTR_PHYS_PATH>();
+ l_path.dump();
+ }
+
+ TS_TRACE(INF_MRK "Found %d targets that are ex/mba units off "
+ "master processor",l_count);
+
+ TS_TRACE(EXIT_MRK "testComplexFilter" );
+ }
};
#endif // End __TESTTARGETING_H
diff --git a/src/usr/targeting/trace.H b/src/usr/targeting/trace.H
index d16ef8ece..e7ffe0365 100644
--- a/src/usr/targeting/trace.H
+++ b/src/usr/targeting/trace.H
@@ -22,6 +22,8 @@ namespace TARGETING
extern trace_desc_t* g_trac_targeting;
}
+#define TARG_LOC TARG_NAMESPACE TARG_CLASS TARG_FN ": "
+
#define TARG_TAG "[TARG]"
#define TARG_ENTER(args...) \
TRACFCOMP(TARGETING::g_trac_targeting,TARG_TAG " " ENTER_MRK " " TARG_NAMESPACE \
OpenPOWER on IntegriCloud