diff --git a/Control/SGTools/SGTools/BaseInfo.h b/Control/SGTools/SGTools/BaseInfo.h
new file mode 100755
index 0000000000000000000000000000000000000000..74868f25ace2519dea70fac606bad536f601e3ee
--- /dev/null
+++ b/Control/SGTools/SGTools/BaseInfo.h
@@ -0,0 +1,902 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: BaseInfo.h,v 1.11 2008-12-15 16:22:45 ssnyder Exp $
+
+/**
+ * @file  SGTools/BaseInfo.h
+ * @author scott snyder
+ * @date Nov 2005
+ * @brief Provide an interface for finding inheritance information
+ *        at run time.
+ *
+ * The @a SG::BaseInfo<T> class provides an interface for finding
+ * inheritance information about class @a T.  In the absence of compiler
+ * support for reflection, the inheritance information must be
+ * explicitly declared.  This is done with the @a SG_BASE macro
+ * and friends.  To declare that class @a D derives from class @a B, use
+ *
+ *@code
+ *   struct B {};
+ *   struct D : public B {};
+ *   SG_BASE (D, B);
+ @endcode
+ *
+ * You can also use multiple inheritance with the @a SG_BASES2
+ * and @a SG_BASES3 macros:
+ *
+ *@code
+ *   struct B1 {};
+ *   struct B2 {};
+ *   struct B3 {};
+ *   struct D : public B1, public B2, public B3 {};
+ *   SG_BASES3 (D, B1, B2, B3);
+ @endcode
+ *
+ * Supporting more than three base classes requires (straightforward)
+ * changes to the code here.
+ *
+ * If any of the derivations are virtual, the corresponding
+ * base class should be within a @a SG_VIRTUAL macro:
+ *    
+ *@code
+ *   struct B1 {};
+ *   struct B2 {};
+ *   struct D : public B1, virtual public B2 {};
+ *   SG_BASES2 (D, B1, SG_VIRTUAL (B2));
+ @endcode
+ *
+ * Note that these macros will only work with non-templated types,
+ * or with specific instantiations of templated types.  If you want
+ * a templated @a SG_BASE, you'll need to declare the specialization
+ * yourself.  You should specialize @a SG::Bases<T>, defining types
+ * @a Base1, @a Base2, and @a Base3 (which should be @a SG::NoBase
+ * if not used).  Example:
+ *
+ *@code
+ *   template <class T> struct B {};
+ *   template <class T> struct D : public B<T> {};
+ *   namespace SG {
+ *     template <class T>
+ *     struct Bases<D<T> > {
+ *       typedef B<T> Base1;
+ *       typedef NoBase Base2;
+ *       typedef NoBase Base3;
+ *     };
+ *   }
+ @endcode
+ *
+ * Once these declarations are in place, what can you do with it?
+ * The interface is provided by the @a SG::BaseInfo<T> class.
+ * (This is a wrapper around a singleton, so it's not expensive
+ * to create instances of this class.)  You can specify the base
+ * classes either by the Gaudi class ID or by the C++ @c std::type_info.
+ * Of course, you'll only be able to get information by class ID
+ * if the classes actually have IDs defined.
+ *
+ * Here are the available methods of @a SG::BaseInfo<T>:
+ *
+ *@code
+ *   static bool is_base (CLID clid)
+ *   static bool is_base (const std::type_info& tinfo)
+ @endcode
+ *     Test to see if the type given by @a clid or @a tinfo
+ *     is a base of @a T.  Note that @a T counts as its own base.
+ *
+ *@code
+ *   static bool is_virtual (CLID clid)
+ *   static bool is_virtual (const std::type_info& tinfo)
+ @endcode
+ *     Test to see if the type given by @a clid or @a tinfo
+ *     is a virtual base of @a T.  This should always be @a false
+ *     for @a T itself.
+ *
+ *@code
+ *   static void* cast (T* p, CLID clid)
+ *   static void* cast (T* p, const std::type_info& tinfo)
+ @endcode
+ *     Cast a pointer from @a T* to a pointer to the type given
+ *     by @a clid or @a tinfo, which must be a base if @a T
+ *     known to @a BaseInfo.  The result is returned as a @a void*.
+ *     If the conversion cannot be done (because the target is not
+ *     known to be a base of @a T), then 0 is returned.
+ *
+ *@code
+ *   static T* castTo (void* p, CLID clid)
+ *   static T* castTo (void* p, const std::type_info& tinfo)
+ @endcode
+ *     Similar, except converts from a pointer to the type given by
+ *     @a clid or @a tinfo (which must be a base of @a T) to @a T*.
+ *     This involves a @a dynamic_cast.  Returns 0 if the cast fails.
+ *
+ *@code
+ *   static std::vector<CLID> get_bases ()
+ @endcode
+ *     Return all the known bases of @a T (that have class IDs).
+ *     @a T itself will be included in this list.
+ *
+ *@code
+ *   static std::vector<const std::type_info*> get_ti_bases ()
+ @endcode
+ *     Return all the known bases of @a T.
+ *     @a T itself will be included in this list.
+ *
+ * It is also possible to get a non-templated version of @c SG::BaseInfo<T>.
+ * This is called @c SG::BaseInfoBase.  These objects can be found using
+ * @c SG::BaseInfoBase::find, by either class ID or @c std::type_info
+ * (in order for this to work, the corresponding @c SG::BaseInfo<T> class
+ * must have been used somewhere in the program).  The interface
+ * of @c SG::BaseInfoBase is the same as @c SG::BaseInfo<T>, except
+ * that @c void* replaces @c T* in the @c cast methods.
+ *
+ * Initialization issues: We don't want to build the @c SG::BaseInfo<T>
+ * objects at static initialization time.  But we do need to remember
+ * which ones are available.  Thus, @c BaseInfoBase maintains a list
+ * of CLIDs and @c std::type_info's for which we may not have done
+ * initialization, along with a function to call to do the initialization.
+ * The initialization list is filled during static initialization.
+ * When we look for an instance, if we don't find one, we look in the
+ * initialization list; if there's a match there, we run the initialization
+ * and remove it from the list.
+ *
+ * Copy conversions: The conversion machinery above provides access to the
+ * standard C++ base<>derived conversions.  However, sometimes you'd like
+ * to allow additional conversions as well, for example between a
+ * vector<ElementLink<T> > and DataVector<T>.  For those cases,
+ * you can register a conversion function with the _source_ type
+ * that can initialize an instance of the _destination_ type
+ * from the _source_ type.  Then, when you try to retrieve the object
+ * from StoreGate with the _destination_ type, your conversion function
+ * will be called.
+ *
+ * Your conversion function should be the method @a convert of
+ * a class deriving from the @a SG::CopyConversion template;
+ * for example,
+ *
+ *@code
+ *   class MyCopyConversion
+ *     : public SG::CopyConversion<std::vector<ElementLink<MyType> >,
+ *                                 DataVector<MyType> >
+ *   {
+ *   public:
+ *     virtual void convert (const std::vector<ElementLink<MyType> >& src,
+ *                           DataVector<MyType>& dst) const
+ *     {
+ *       size_t sz = src.size();
+ *       if (dst.size() != sz) {
+ *         dst.clear (SG::VIEW_ELEMENTS);
+ *         dst.reserve (sz);
+ *         for (size_t i = 0; i < sz; i++) {
+ *           const MyType* p = *(src[i]).cptr(); 
+ *           dst.push_back (const_cast<MyType*> (p));
+ *         }
+ *       }
+ *     }
+ *   };
+ @endcode
+ *
+ * You then declare this using the macro
+ *
+ @code
+ *  SG_ADD_COPY_CONVERSION (std::vector<ElementLink<MyType> >,
+ *                          MyCopyConversion);
+ @endcode
+ *
+ * Copy conversions are enabled only for objects that have been marked as const.
+ */
+
+#ifndef SGTOOLS_BASEINFO_H
+#define SGTOOLS_BASEINFO_H
+
+#include "GaudiKernel/ClassID.h"
+#include <vector>
+#include <typeinfo>
+
+
+//===========================================================================
+// Macros used to declare base class information.
+//
+
+/**
+ * @brief Used to mark virtual derivation.
+ *        When using the @a SG_BASE macros below, use this in the case
+ *        of virtual derivation.  Example:
+ *
+ *@code
+ *   struct B1 {};
+ *   struct B2 {};
+ *   struct D : public B1, virtual public B2 {};
+ *   SG_BASES2 (D, B1, SG_VIRTUAL (B2));
+ @endcode
+ */
+#define SG_VIRTUAL(T) Virtual<T>
+
+
+/**
+ * @brief Declare that class @a D derives from class @a B.  Example:
+ *
+ *@code
+ *   struct B {};
+ *   struct D : public B {};
+ *   SG_BASE (D, B);
+ @endcode
+ */
+#define SG_BASE(D, B) SG_BASES1(D, B)
+
+
+/**
+ * @brief Declare that class @a D derives from class @a B.
+ *        This is the same as @a SG_BASE.  Example:
+ *
+ *@code
+ *   struct B {};
+ *   struct D : public B {};
+ *   SG_BASES1 (D, B);
+ @endcode
+ */
+#define SG_BASES1(D, B)          \
+  namespace SG        {          \
+    template<> struct Bases<D >{ \
+      typedef B Base1;           \
+      typedef NoBase Base2;      \
+      typedef NoBase Base3;      \
+    };                           \
+    template struct BaseInit<D >; \
+} struct sg_dummy // to swallow semicolon
+
+
+/**
+ * @brief Declare that class @a D derives from classes @a B1 and @a B2.
+ *        Example:
+ *
+ *@code
+ *   struct B1 {};
+ *   struct B2 {};
+ *   struct D : public B1, public B2 {};
+ *   SG_BASES2 (D, B1, B2);
+ @endcode
+ */
+#define SG_BASES2(D, B1, B2)     \
+  namespace SG        {          \
+    template<> struct Bases<D >{ \
+      typedef B1 Base1;          \
+      typedef B2 Base2;          \
+      typedef NoBase Base3;      \
+    };                           \
+    template struct BaseInit<D >; \
+} struct sg_dummy // to swallow semicolon
+
+
+/**
+ * @brief Declare that class @a D derives from classes @a B1, @a B2, and @a B3.
+ *        Example:
+ *
+ *@code
+ *   struct B1 {};
+ *   struct B2 {};
+ *   struct B3 {};
+ *   struct D : public B1, public B2, public B3 {};
+ *   SG_BASES3 (D, B1, B2, B3);
+ @endcode
+ */
+#define SG_BASES3(D, B1, B2, B3) \
+  namespace SG        {          \
+    template<> struct Bases<D >{ \
+      typedef B1 Base1;          \
+      typedef B2 Base2;          \
+      typedef B3 Base3;          \
+    };                           \
+    template struct BaseInit<D >; \
+} struct sg_dummy // to swallow semicolon
+
+
+
+/**
+ * @brief Add a new base class @c B to class @c D.
+ *
+ * Sometimes, the SG_BASE macro for a class isn't present in its header.
+ *
+ * One can try to put the appropriate SG_BASE macro somewhere else,
+ * but this doesn't always work: if the @c BaseInfoBase for @c D has
+ * already been created by the time the @c SG_BASE initialization
+ * runs, then that @c SG_BASE macro won't do anything.
+ *
+ * @c SG_ADD_BASE, however, will add a new base to an existing @c BaseInfoBase.
+ *
+ *@code
+ *   struct B {};
+ *   struct D : public B {};
+ *   SG_ADD_BASES (D, B);
+ @endcode
+ */
+#define SG_ADD_BASE(D, B) \
+  namespace SG        {          \
+    template struct AddBaseInit<D, B >;            \
+} struct sg_dummy // to swallow semicolon
+
+
+/**
+ * @brief Declare a copy conversion from class @c T using converter @c C.
+ *
+ * See the comments in the header for a detailed description.
+ */
+#define SG_ADD_COPY_CONVERSION(D, C) \
+  namespace SG        {          \
+    template struct AddCopyConversionInit<D, C >;            \
+} struct sg_dummy // to swallow semicolon
+
+
+
+namespace SG {
+
+
+/**
+ * @brief Helper metafunction to get base class types.
+ *
+ * For a class @c T,
+ *@code
+ *   SG::BaseType<SG::Bases<T>::Base1>::type
+ @endcode
+ * gives the type of @c T's first base.  Also,
+ *@code
+ *   SG::BaseType<SG::Bases<T>::Base1>::is_virtual
+ @endcode
+ * tells whether the derivation is virtual
+ * (either @c true_type or @c false_type).
+ *
+ * Note that @c SG::Bases\<T>::Base1 is not the actual type
+ * of @c T's first base if virtual derivation was used.
+ */
+template <class T>
+struct BaseType;
+
+
+// Forward declaration.
+template <class T>
+class BaseInfoImpl;
+
+
+struct BaseInfoBaseImpl;
+
+
+//===========================================================================
+// Copy conversion declarations.
+//
+
+
+/**
+ * @brief Base class for copy conversions.
+ */
+class CopyConversionBase
+{
+public:
+  /// Destructor.
+  virtual ~CopyConversionBase() {}
+
+  /// Create an instance of the destination class.
+  virtual void* create() const = 0;
+
+  /// Destroy an instance of the destination class.
+  virtual void destroy (void* p) const = 0;
+
+  /// Convert the contents of an instance of the source class SRC
+  /// to an instance of the destination class DST.
+  virtual void convertUntyped (const void* src, void* dst) const = 0;
+};
+
+
+/**
+ * @brief Base class for copy conversions, templated on source
+ *        and destination classes.
+ */
+template <class SRC, class DST>
+class CopyConversion
+  : public CopyConversionBase
+{
+public:
+  /// The destination class.
+  typedef DST target_type;
+
+  /// Create an instance of the destination class.
+  virtual void* create() const { return new DST; }
+
+  /// Destroy an instance of the destination class.
+  virtual void destroy (void* p) const { delete reinterpret_cast<DST*>(p); }
+
+  /// Convert the contents of an instance of the source class SRC
+  /// to an instance of the destination class DST.
+  virtual void convertUntyped (const void* src, void* dst) const
+  {
+    convert (*reinterpret_cast<const SRC*>(src),
+             *reinterpret_cast<DST*>(dst));
+  }
+
+  /// Convert the contents of an instance of the source class SRC
+  /// to an instance of the destination class DST.
+  /// (Type-safe version.)
+  virtual void convert (const SRC& src, DST& dst) const = 0;
+};
+
+
+//===========================================================================
+// Base class declaration.
+// This factors out the part of the implementation that doesn't
+// depend on the template parameter @a T.
+//
+
+
+/**
+ * @brief The non-template portion of the @a BaseInfo implementation.
+ */
+class BaseInfoBase
+{
+public:
+  /**
+   * @brief Return the CLID for this class.
+   */
+  CLID clid() const;
+
+
+  /**
+   * @brief Return the @c std::type_info for this class.
+   */
+  const std::type_info& typeinfo() const;
+  
+
+  /**
+   * @brief Cast to a base pointer.
+   * @param p The pointer to cast (a @a T* cast to a @a void*).
+   * @param clid ID of the class to which to cast.
+   * @return The pointer cast to the requested type, returned
+   *         as a @a void*.  @a clid must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   */
+  void* cast (void* p, CLID clid) const;
+
+  /**
+   * @brief Cast to a base pointer.
+   * @param p The pointer to cast (a @a T* cast to a @a void*).
+   * @param clid @a type_info of the class to which to cast.
+   * @return The pointer cast to the requested type, returned
+   *         as a @a void*.  @a tinfo must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   */
+  void* cast (void* p, const std::type_info& tinfo) const;
+
+
+  /**
+   * @brief Cast to a derived pointer.
+   * @param p The pointer to cast (a @a B* cast to a @a void*).
+   * @param clid ID of the class @a B from which to cast.
+   * @return The pointer cast to the requested type, returned
+   *         as a @a void*.  @a clid must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   *         0 will also be returned if the @a dynamic_cast fails.
+   */
+  void* castTo (void* p, CLID clid) const;
+
+  /**
+   * @brief Cast to a derived pointer.
+   * @param p The pointer to cast (a @a B* cast to a @a void*).
+   * @param clid @a type_info of the class @a B from which to cast.
+   * @return The pointer cast to the requested type, returned
+   *         as a @a void*.  @a tinfo must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   *         0 will also be returned if the @a dynamic_cast fails.
+   */
+  void* castTo (void* p, const std::type_info& tinfo) const;
+
+
+  /// Type of a pointer conversion function.
+  typedef void* castfn_t (void* p);
+
+
+  // gcc 4.3 complains about the code genreflex generates for these.
+  // They're not useful from python anyway, so just suppress them.
+#ifndef __REFLEX__
+  /**
+   * @brief Return a function for casting to a base pointer.
+   * @param clid ID of the class to which to cast.
+   * @return A function to convert a pointer to a @c T to a pointer
+   *         to the type identified by @a clid.
+   *         @a clid must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   */
+  castfn_t* castfn (CLID clid) const;
+
+
+  /**
+   * @brief Return a function for casting to a base pointer.
+   * @param clid @a type_info of the class to which to cast.
+   * @return A function to convert a pointer to a @c T to a pointer
+   *         to the type identified by @a tinfo.
+   *         @a tinfo must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   */
+  castfn_t* castfn (const std::type_info& tinfo) const;
+
+  /**
+   * @brief Return a function for casting to a derived pointer.
+   * @param clid ID of the class @a B from which to cast.
+   * @return A function to convert a pointer to a @a B to a pointer
+   *         to a @a T.  @a B must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   *         0 will also be returned if the @a dynamic_cast fails.
+   */
+  castfn_t* castfnTo (CLID clid) const;
+
+
+  /**
+   * @brief Return a function for casting to a derived pointer.
+   * @param clid @a type_info of the class @a B from which to cast.
+   * @return A function to convert a pointer to a @a B to a pointer
+   *         to a @a T.  @a B must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   *         0 will also be returned if the @a dynamic_cast fails.
+   */
+  castfn_t* castfnTo (const std::type_info& tinfo) const;
+#endif
+
+
+  /**
+   * @brief Return the class IDs of all known bases of @a T (that
+   *        have class IDs).  The list will include @a T itself.
+   */
+  std::vector<CLID> get_bases () const;
+
+  /**
+   * @brief Return the @c type_info's of all known bases of @a T.
+   *        The list will include @a T itself.
+   */
+  std::vector<const std::type_info*> get_ti_bases () const;
+
+  /**
+   * @brief Return true if @a clid is the ID of a class that
+   *        is known to be a base of @a T.  @a T is considered
+   *        to be its own base for this purpose.
+   * @param clid The ID of the class to test.
+   */
+  bool is_base (CLID clid) const;
+
+  /**
+   * @brief Return true if @a tinfo is the @a type_info of a class that
+   *        is known to be a base of @a T.  @a T is considered
+   *        to be its own base for this purpose.
+   * @param clid The ID of the class to test.
+   */
+  bool is_base (const std::type_info& tinfo) const;
+
+
+  /**
+   * @brief Return true if @a clid is the ID of a class that
+   *        is known to be a virtual base of @a T.  (This will always
+   *        be false for @a T itself.)
+   * @param clid The ID of the class to test.
+   */
+  bool is_virtual (CLID clid) const;
+
+  /**
+   * @brief Return true if @a tinfo is the @a std::type_info of a class that
+   *        is known to be a virtual base of @a T.  (This will always
+   *        be false for @a T itself.)
+   * @param tinfo The @a std::type_info of the class to test.
+   */
+  bool is_virtual (const std::type_info& tinfo) const;
+
+
+  /**
+   * @brief Search for a copy conversion to @c tinfo.
+   * @param tinfo The class to which we want to convert.
+   *
+   * Returns the conversion instance or 0.
+   */
+  const CopyConversionBase* copy_conversion (const std::type_info& tinfo) const;
+
+
+  /**
+   * @brief Search for a copy conversion to @c clid.
+   * @param clid The class to which we want to convert.
+   *
+   * Returns the conversion instance or 0.
+   */
+  const CopyConversionBase* copy_conversion (CLID clid) const;
+
+
+  /**
+   * @brief Add a new copy conversion.
+   * @param clid The @c CLID of the target class.
+   * @param tinfo The @c std::type_info of the target class.
+   * @param cnv A @c CopyConversionBase instance describing the conversion.
+   *
+   * The @c BaseInfoBase takes ownership of the @c cnv object.
+   */
+  void add_copy_conversion (CLID clid,
+                            const std::type_info& tinfo,
+                            const CopyConversionBase* cnv);
+
+
+  /**
+   * @brief Return known copy conversions.
+   *
+   * Returns the CLIDs of all target classes that have been registered
+   * with this one for copy conversion.
+   */
+  std::vector<CLID> get_copy_conversions() const;
+
+
+#ifndef __REFLEX__
+  /**
+   * @brief Add information about one base class.
+   * @param clid The class ID of the base.  May be @a CLID_NULL if no
+   *             class ID is available.
+   * @param tinfo The @a std::type_info of the base.
+   * @param converter Converter function.  This should be able to
+   *                  convert a @a T* to a pointer to this base.
+   * @param converterTo Converter function.  This should be able to
+   *                    convert a pointer to this base to a @a T*.
+   * @param is_virtual True if the derivation from this base to @a T
+   *                   is via virtual derivation.
+   */
+  void add_info (CLID clid,
+                 const std::type_info& tinfo,
+                 castfn_t* converter,
+                 castfn_t* converterTo,
+                 bool is_virtual);
+#endif
+
+
+  /**
+   * @brief Find the @c BaseInfoBase instance for @c clid.
+   * @param clid The class ID of the class for which we want information.
+   *
+   * Returns 0 if no @c BaseInfoBase instance is available.
+   */
+  static const BaseInfoBase* find (CLID clid);
+
+
+  /**
+   * @brief Find the @c BaseInfoBase instance for @c tinfo.
+   * @param tinfo The @c std::type_info of the class
+   *              for which we want information.
+   *
+   * Returns 0 if no @c BaseInfoBase instance is available.
+   */
+  static const BaseInfoBase* find (const std::type_info& tinfo);
+
+
+  /// Type for an initialization function.
+  typedef const BaseInfoBase& init_func_t();
+
+
+#ifndef __REFLEX__
+  /**
+   * @brief Register an initialization function.
+   * @param clid The class ID of the class being registered.
+   * @param tinfo The @c std::type_info for the class being registered.
+   * @param init_func Function to initialize @c BaseInfo for the class.
+   */
+  static void addInit (CLID clid,
+                       const std::type_info* tinfo,
+                       init_func_t* init_func);
+#endif
+
+
+  /**
+   * @brief Run initializations for this class, if needed.
+   */
+  void maybeInit();
+
+
+protected:
+  /**
+   * @brief Constructor.
+   * @param clid The class ID of this class.  May be @c CLID_NULL if no
+   *             ID is available.
+   * @param tinfo The @c std::type_info for this class.
+   */
+  BaseInfoBase (CLID clid, const std::type_info& tinfo);
+
+
+  /**
+   * @brief Destructor.
+   */
+  ~BaseInfoBase();
+
+
+private:
+  /**
+   * @brief Try to translate a type_info to a CLID by looking in the initlist.
+   * @param tinfo The type to translate.
+   * @returns The corresponding CLID, or CLID_NULL.
+   */
+  CLID clid_from_initlist (const std::type_info& tinfo);
+
+
+  /// Pointer to internal state.
+  BaseInfoBaseImpl* m_impl;
+
+  BaseInfoBase (const BaseInfoBase&);
+  BaseInfoBase& operator= (const BaseInfoBase&);
+};
+
+
+//===========================================================================
+// The templated @c BaseInfo class.
+//
+
+/**
+ * @brief Provide an interface for finding inheritance information
+ *        at run time.  See the file comments for full details.
+ */
+template <class T>
+class BaseInfo
+{
+public:
+  /**
+   * @brief Cast to a base pointer.
+   * @param p The pointer to cast.
+   * @param clid ID of the class to which to cast.
+   * @return The pointer cast to the requested type, returned
+   *         as a @a void*.  @a clid must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   */
+  static void* cast (T* p, CLID clid);
+
+  /**
+   * @brief Cast to a base pointer.
+   * @param p The pointer to cast.
+   * @param clid @a type_info of the class to which to cast.
+   * @return The pointer cast to the requested type, returned
+   *         as a @a void*.  @a tinfo must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   */
+  static void* cast (T* p, const std::type_info& tinfo);
+
+
+  /**
+   * @brief Cast to a derived pointer.
+   * @param p The pointer to cast.
+   * @param clid ID of the class @a B from which to cast.
+   * @return The pointer cast to a @a T*.
+   *         @a B must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   *         0 will also be returned if the @a dynamic_cast fails.
+   */
+  static T* castTo (void* p, CLID clid);
+
+  /**
+   * @brief Cast to a derived pointer.
+   * @param p The pointer to cast.
+   * @param clid @a type_info of the class @a B from which to cast.
+   * @return The pointer cast to a @a T*.
+   *         @a B must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   *         0 will also be returned if the @a dynamic_cast fails.
+   */
+  static T* castTo (void* p, const std::type_info& tinfo);
+
+
+  /**
+   * @brief Return a function for casting to a base pointer.
+   * @param clid ID of the class to which to cast.
+   * @return A function to convert a pointer to a @c T to a pointer
+   *         to the type identified by @a clid.
+   *         @a clid must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   */
+  static BaseInfoBase::castfn_t* castfn (CLID clid);
+
+
+  /**
+   * @brief Return a function for casting to a base pointer.
+   * @param clid @a type_info of the class to which to cast.
+   * @return A function to convert a pointer to a @c T to a pointer
+   *         to the type identified by @a tinfo.
+   *         @a tinfo must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   */
+  static BaseInfoBase::castfn_t* castfn (const std::type_info& tinfo);
+
+
+  /**
+   * @brief Return a function for casting to a derived pointer.
+   * @param clid ID of the class @a B from which to cast.
+   * @return A function to convert a pointer to a @c T to a pointer
+   *         to a @a T.  @a clid must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   *         0 will also be returned if the @a dynamic_cast fails.
+   */
+  static BaseInfoBase::castfn_t* castfnTo (CLID clid);
+
+
+  /**
+   * @brief Return a function for casting to a derived pointer.
+   * @param clid @a type_info of the class @a B from which to cast.
+   * @return A function to convert a pointer to a @c B to a pointer
+   *         to a @T.  @a tinfo must be known to be a base
+   *         of @a T; otherwise, 0 will be returned.
+   *         0 will also be returned if the @a dynamic_cast fails.
+   */
+  static BaseInfoBase::castfn_t* castfnTo (const std::type_info& tinfo);
+
+
+  /**
+   * @brief Return the class IDs of all known bases of @a T (that
+   *        have class IDs).  The list will include @a T itself.
+   */
+  static std::vector<CLID> get_bases ();
+
+
+  /**
+   * @brief Return the @c type_info's of all known bases of @a T.
+   *        The list will include @a T itself.
+   */
+  static std::vector<const std::type_info*> get_ti_bases ();
+
+
+  /**
+   * @brief Return true if @a clid is the ID of a class that
+   *        is known to be a base of @a T.  @a T is considered
+   *        to be its own base for this purpose.
+   * @param clid The ID of the class to test.
+   */
+  static bool is_base (CLID clid);
+
+  /**
+   * @brief Return true if @a tinfo is the @a std::type_info of a class that
+   *        is known to be a base of @a T.  @a T is considered
+   *        to be its own base for this purpose.
+   * @param tinfo The @a std::type_info of the class to test.
+   */
+  static bool is_base (const std::type_info& tinfo);
+
+
+  /**
+   * @brief Return true if @a clid is the ID of a class that
+   *        is known to be a virtual base of @a T.  (This will always
+   *        be false for @a T itself.)
+   * @param clid The ID of the class to test.
+   */
+  static bool is_virtual (CLID clid);
+
+  /**
+   * @brief Return true if @a tinfo is the @a std::type_info of a class that
+   *        is known to be a virtual base of @a T.  (This will always
+   *        be false for @a T itself.)
+   * @param tinfo The @a std::type_info of the class to test.
+   */
+  static bool is_virtual (const std::type_info& tinfo);
+
+
+  /**
+   * @brief Return the non-templated @c BaseInfoBase object for this type.
+   */
+  static const BaseInfoBase& baseinfo ();
+
+
+private:
+  /// Return a reference to the (singleton) implementation object
+  /// for this class.
+  static const BaseInfoImpl<T>& instance();
+
+  /// This holds the singleton implementation object instance.
+  struct instance_holder
+  {
+    instance_holder();
+    BaseInfoImpl<T>* instance;
+  };
+  static instance_holder s_instance;
+};
+
+
+} // namespace SG
+
+
+#include "SGTools/BaseInfo.icc"
+
+
+#endif // not SGTOOLS_BASEINFO_H
+
diff --git a/Control/SGTools/SGTools/BaseInfo.icc b/Control/SGTools/SGTools/BaseInfo.icc
new file mode 100755
index 0000000000000000000000000000000000000000..9524cca44423fb2fc00232690b16a1ee8fae3491
--- /dev/null
+++ b/Control/SGTools/SGTools/BaseInfo.icc
@@ -0,0 +1,654 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: BaseInfo.icc,v 1.9 2008-12-15 15:12:39 ssnyder Exp $
+/**
+ * @file  SGTools/BaseInfo.icc
+ * @author scott snyder
+ * @date Nov 2005
+ * @brief Provide an interface for finding inheritance information
+ *        at run time.
+ *        Implementation file.
+ */
+
+
+#include "SGTools/safe_clid.h"
+#include "boost/type_traits/is_polymorphic.hpp"
+
+
+namespace SG {
+
+
+//===========================================================================
+// Inheritance data representation classes.
+//
+
+
+/**
+ * @brief Marker to indicate a nonexistent base class.
+ */
+struct NoBase {};
+
+
+/**
+ * @brief Wrapper to indicate virtual derivation.
+ *        @a Virtual<T> will mean that derivation from @a T is virtual.
+ */
+template <class T> struct Virtual {};
+
+
+/**
+ * @brief Traits class to hold derivation information for up to three
+ *        base classes.
+ *
+ * @a Base1, etc., get typedef'd to the appropriate
+ * base classes.  Use @a NoBase if there is no base class; use
+ * @a Virtual<T> to indicate virtual derivation.  This class should
+ * be specialized for every class @a T for which we want to know
+ * inheritance information.
+ */
+template <class T>
+struct Bases
+{
+  typedef NoBase Base1;
+  typedef NoBase Base2;
+  typedef NoBase Base3;
+};
+
+
+// Helper metafunction to get base class types.
+// Generic case.
+template <class T>
+struct BaseType
+{
+  typedef T type;
+  typedef boost::false_type is_virtual;
+};
+
+
+// Helper metafunction to get base class types.
+// Virtual derivation case.
+template <class T>
+struct BaseType<Virtual<T> >
+{
+  typedef T type;
+  typedef boost::true_type is_virtual;
+};
+
+
+//===========================================================================
+// Internal implementation class for @a BaseInfo.
+// This is used as a singleton, and should be accessed using the @a BaseInfo
+// wrapper class.
+//
+
+/**
+ * @brief Internal implementation class for @a BaseInfo.
+ */
+template <class T>
+class BaseInfoImpl
+  : public BaseInfoBase
+{
+public:
+  /**
+   * @brief Constructor.
+   */
+  BaseInfoImpl();
+
+
+  /**
+   * @brief Add information about base class @a B (for @a T).
+   * @param is_virtual True if the derivation from @a B to @a T
+   *                   is via virtual derivation.
+   */
+#ifdef __REFLEX__
+  template <class B>
+  void add_base (bool is_virtual);
+#else
+  template <class B>
+  void add_base (bool is_virtual)
+  {
+    // Add the information for this base.
+    // Note the use of @a safe_clid to allow this to work whether or not
+    // there is actually a class ID defined for @a B.
+    // We pass in the converter function and the virtual flag.
+    this->add_info (SG::safe_clid<B>(), typeid(B),
+                    converter<B>, converterTo<B>, is_virtual);
+  }
+#endif
+
+private:
+  /**
+   * @brief Converter function.
+   * @param p Pointer to convert.  A @a T* converted to a @a void*.
+   *
+   * Converts a @a T* to a @a B* (where @a T derives from @a B).
+   * The pointers are given and returned as @a void*.
+   */
+  template <class B>
+  static void* converter (void* p)
+  {
+    B* b = reinterpret_cast<T*> (p);
+    return b;
+  }
+
+
+  /**
+   * @brief Converter function.
+   * @param p Pointer to convert.  A @a B* converted to a @a void*.
+   *
+   * Converts a @a B* to a @a T* (where @a T derives from @a B).
+   * The pointers are given and returned as @a void*.
+   * Returns 0 if the conversion fails.
+   *
+   * Implementation note: to @c dynamic_cast @a B to @a T, @a B needs to have
+   * a vtable.  If B doesn't have a vtable, then we don't attempt the
+   * conversion.  (In principle, we could use is_virtual_base_of, and fall
+   * back to a static_cast if it's false.  However, using is_virtual_base_of
+   * generates some nasty compilation warnings, so i'll avoid it for now.)
+   */
+  template <class B>
+  static void* converterTo (void* p)
+  {
+    return converterToHelper<B> (p, boost::is_polymorphic<B>());
+  }
+
+
+  // B has a vtable.  Use dynamic_cast.
+  template <class B>
+  static void* converterToHelper (void* p, boost::true_type)
+  {
+    T* b = dynamic_cast<T*> (reinterpret_cast<B*> (p));
+    return b;
+  }
+
+
+  // B doesn't have a vtable.  Don't try to convert.
+  template <class B>
+  static void* converterToHelper (void* /*p*/, boost::false_type)
+  {
+    return 0;
+  }
+};
+
+
+//===========================================================================
+// Initialization.
+// Here we walk the class hierarchy, calling @a add_base for each base.
+
+
+/**
+ * @brief Generic initializer for base @a B.
+ */
+template <class B>
+struct BaseInfo_init
+{
+  template <class T>
+  static void init (BaseInfoImpl<T>& c, bool is_virtual)
+  {
+    // Here, we initialize the @a BaseInfo for @a T for base class @a B.
+    // First, we add the information for this base to the instance.
+    c.template add_base<B>(is_virtual);
+
+    // Then we recurse on each possible base.
+    BaseInfo_init<typename Bases<B>::Base1>::init (c, is_virtual);
+    BaseInfo_init<typename Bases<B>::Base2>::init (c, is_virtual);
+    BaseInfo_init<typename Bases<B>::Base3>::init (c, is_virtual);
+  }
+};
+
+
+/**
+ * @brief Dummy initializer.
+ */
+template <>
+struct BaseInfo_init<NoBase>
+{
+  template <class T>
+  static void init (BaseInfoImpl<T>& /*c*/, bool /*is_virtual*/)
+  {
+    // This gets called when there is no base in a slot
+    // (signaled by the use of @a NoBase).
+    // This ends the recursion.
+  }
+};
+
+
+/**
+ * @brief Initializer for virtual base @a B.
+ */
+template <class B>
+struct BaseInfo_init<Virtual<B> >
+{
+  template <class T>
+  static void init (BaseInfoImpl<T>& c, bool /*is_virtual*/)
+  {
+    // Here, we initialize the @a BaseInfo for @a T for a virtual
+    // base class @a B.  We recurse to the generic initializer
+    // for this base, with the @a is_virtual flag forced on.
+    BaseInfo_init<B>::init (c, true);
+  }
+};
+
+
+/**
+ * @brief Constructor.
+ */
+template <class T>
+BaseInfoImpl<T>::BaseInfoImpl ()
+  : BaseInfoBase (SG::safe_clid<T>(), typeid(T))
+{
+  // This starts the walk over the bases.
+  // We start with @a T itself.
+  // The virtual flag is initially false.
+  BaseInfo_init<T>::init (*this, false);
+}
+
+
+//===========================================================================
+// The @a BaseInfo wrapper class.
+// This will statically hold a singleton instance of @a BaseInfoImpl
+// (in the instance function).
+
+
+/**
+ * @brief Cast to a base pointer.
+ * @param p The pointer to cast.
+ * @param clid ID of the class to which to cast.
+ * @return The pointer cast to the requested type, returned
+ *         as a @a void*.  @a clid must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ */
+template <class T>
+void* BaseInfo<T>::cast (T* p, CLID clid)
+{
+  return instance().cast (p, clid);
+}
+
+
+/**
+ * @brief Cast to a base pointer.
+ * @param p The pointer to cast.
+ * @param clid @a type_info of the class to which to cast.
+ * @return The pointer cast to the requested type, returned
+ *         as a @a void*.  @a tinfo must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ */
+template <class T>
+void* BaseInfo<T>::cast (T* p, const std::type_info& tinfo)
+{
+  return instance().cast (p, tinfo);
+}
+
+
+/**
+ * @brief Cast to a derived pointer.
+ * @param p The pointer to cast.
+ * @param clid ID of the class @a B from which to cast.
+ * @return The pointer cast to a @a T*.
+ *         @a B must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ *         0 will also be returned if the @a dynamic_cast fails.
+ */
+template <class T>
+T* BaseInfo<T>::castTo (void* p, CLID clid)
+{
+  return reinterpret_cast<T*> (instance().castTo (p, clid));
+}
+
+
+/**
+ * @brief Cast to a derived pointer.
+ * @param p The pointer to cast.
+ * @param clid @a type_info of the class @a B from which to cast.
+ * @return The pointer cast to a @a T*.
+ *         @a B must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ *         0 will also be returned if the @a dynamic_cast fails.
+ */
+template <class T>
+T* BaseInfo<T>::castTo (void* p, const std::type_info& tinfo)
+{
+  return reinterpret_cast<T*> (instance().castTo (p, tinfo));
+}
+
+
+#ifndef __REFLEX__
+/**
+ * @brief Return a function for casting to a base pointer.
+ * @param clid ID of the class to which to cast.
+ * @return A function to convert a pointer to a @c T to a pointer
+ *         to the type identified by @a clid.
+ *         @a clid must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ */
+template <class T>
+BaseInfoBase::castfn_t* BaseInfo<T>::castfn (CLID clid)
+{
+  return instance().castfn (clid);
+}
+
+
+/**
+ * @brief Return a function for casting to a base pointer.
+ * @param clid @a type_info of the class to which to cast.
+ * @return A function to convert a pointer to a @c T to a pointer
+ *         to the type identified by @a tinfo.
+ *         @a tinfo must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ */
+template <class T>
+BaseInfoBase::castfn_t*
+BaseInfo<T>::castfn (const std::type_info& tinfo)
+{
+  return instance().castfn (tinfo);
+}
+
+
+/**
+ * @brief Return a function for casting to a derived pointer.
+ * @param clid ID of the class @a B from which to cast.
+ * @return A function to convert a pointer to a @c T to a pointer
+ *         to a @a T.  @a clid must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ *         0 will also be returned if the @a dynamic_cast fails.
+ */
+template <class T>
+BaseInfoBase::castfn_t* BaseInfo<T>::castfnTo (CLID clid)
+{
+  return instance().castfnTo (clid);
+}
+
+
+/**
+ * @brief Return a function for casting to a derived pointer.
+ * @param clid @a type_info of the class @a B from which to cast.
+ * @return A function to convert a pointer to a @c B to a pointer
+ *         to a @T.  @a tinfo must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ *         0 will also be returned if the @a dynamic_cast fails.
+ */
+template <class T>
+BaseInfoBase::castfn_t*
+BaseInfo<T>::castfnTo (const std::type_info& tinfo)
+{
+  return instance().castfnTo (tinfo);
+}
+#endif
+
+
+/**
+ * @brief Return the class IDs of all known bases of @a T (that
+ *        have class IDs).  The list will include @a T itself.
+ */
+template <class T>
+std::vector<CLID> BaseInfo<T>::get_bases ()
+{
+  return instance().get_bases();
+}
+
+
+/**
+ * @brief Return the @c type_info's of all known bases of @a T.
+ *        The list will include @a T itself.
+ */
+template <class T>
+std::vector<const std::type_info*>
+BaseInfo<T>::get_ti_bases ()
+{
+  return instance().get_ti_bases();
+}
+
+
+/**
+ * @brief Return true if @a clid is the ID of a class that
+ *        is known to be a base of @a T.  @a T is considered
+ *        to be its own base for this purpose.
+ * @param clid The ID of the class to test.
+ */
+template <class T>
+bool BaseInfo<T>::is_base (CLID clid)
+{
+  return instance().is_base (clid);
+}
+
+
+/**
+ * @brief Return true if @a tinfo is the @a std::type_info of a class that
+ *        is known to be a base of @a T.  @a T is considered
+ *        to be its own base for this purpose.
+ * @param tinfo The @a std::type_info of the class to test.
+ */
+template <class T>
+bool BaseInfo<T>::is_base (const std::type_info& tinfo)
+{
+  return instance().is_base (tinfo);
+}
+
+
+/**
+ * @brief Return true if @a clid is the ID of a class that
+ *        is known to be a virtual base of @a T.  (This will always
+ *        be false for @a T itself.)
+ * @param clid The ID of the class to test.
+ */
+template <class T>
+bool BaseInfo<T>::is_virtual (CLID clid)
+{
+  return instance().is_virtual (clid);
+}
+
+
+/**
+ * @brief Return true if @a tinfo is the @a std::type_info of a class that
+ *        is known to be a virtual base of @a T.  (This will always
+ *        be false for @a T itself.)
+ * @param tinfo The @a std::type_info of the class to test.
+ */
+template <class T>
+bool BaseInfo<T>::is_virtual (const std::type_info& tinfo)
+{
+  return instance().is_virtual (tinfo);
+}
+
+
+/**
+ * @brief Return the non-templated @c BaseInfoBase object for this type.
+ */
+template <class T>
+const BaseInfoBase& BaseInfo<T>::baseinfo()
+{
+  return instance();
+}
+
+
+/**
+ * @brief Return a reference to the (singleton) implementation object
+ *        for this class.
+ */
+template <class T>
+const BaseInfoImpl<T>& BaseInfo<T>::instance()
+{
+  BaseInfoImpl<T>* inst = s_instance.instance;
+  if (inst)
+    inst->maybeInit();
+  return *inst;
+}
+
+
+/**
+ * @brief Constructor to get the singleton instance set up.
+ */
+template <class T>
+BaseInfo<T>::instance_holder::instance_holder()
+{
+  static BaseInfoImpl<T> inst;
+  instance = &inst;
+}
+
+
+/// Declare the static member of @c BaseInfo.
+template <class T>
+typename BaseInfo<T>::instance_holder BaseInfo<T>::s_instance;
+
+
+/**
+ * @brief Helper to get @c BaseInfo initialized.
+ */
+template <class T>
+struct RegisterBaseInit
+{
+  RegisterBaseInit();
+};
+
+
+#ifndef __REFLEX__
+template <class T>
+RegisterBaseInit<T>::RegisterBaseInit()
+{
+  BaseInfoBase::addInit(SG::safe_clid<T>(), &typeid(T), BaseInfo<T>::baseinfo);
+}
+#endif
+
+
+/**
+ * @brief Helper to get @c BaseInfo initialized.
+ */
+template <class T> struct BaseInit {
+  static RegisterBaseInit<T> s_regbase;
+};
+#ifndef __APPLE__
+template <class T> RegisterBaseInit<T> BaseInit<T>::s_regbase;
+#endif
+
+
+//**********************************************************
+// SG_ADD_BASE and SG_ADD_COPY_CONVERSION implementation.
+
+
+/**
+ * @brief Helper to get @c AddBaseInfo initialized.
+ */
+template <class D, class B>
+struct RegisterAddBaseInit
+{
+  /// Add ourself to the init list.
+  RegisterAddBaseInit();
+
+  /// Init callback: add the new base to the BIB.
+  static const BaseInfoBase& doinit();
+};
+
+
+#ifndef __REFLEX__
+/**
+ * @brief Init callback: add the new base to the BIB.
+ */
+template <class D, class B>
+const BaseInfoBase& RegisterAddBaseInit<D, B>::doinit()
+{
+  // B may either be the actual base class we want,
+  // or Virtual<BB>. Unwrap a surrounding Virtual<> if needed.
+  typedef typename BaseType<B>::type base_type;
+  bool is_virtual = BaseType<B>::is_virtual::value;
+
+  // Look up the BIB.
+  SG::BaseInfoBase* bib =
+    const_cast<SG::BaseInfoBase*> (SG::BaseInfoBase::find (typeid(D)));
+  if (!bib)
+    bib = const_cast<SG::BaseInfoBase*> (&BaseInfo<D>::baseinfo());
+  if (bib) {
+    // Add the new base to it.
+    SG::BaseInfoImpl<D>& impl = *static_cast<SG::BaseInfoImpl<D>*> (bib);
+    impl.template add_base<base_type> (is_virtual);
+  }
+  return *bib;
+}
+
+
+/**
+ * @brief Add ourself to the init list.
+ */
+template <class D, class B>
+RegisterAddBaseInit<D, B>::RegisterAddBaseInit()
+{
+  BaseInfoBase::addInit(SG::safe_clid<D>(), &typeid(D), doinit);
+}
+#endif
+
+
+/**
+ * @brief Helper to get @c AddBaseInfo initialized.
+ */
+template <class D, class B> struct AddBaseInit {
+  static RegisterAddBaseInit<D, B> s_regbase;
+};
+#ifndef __APPLE__
+template <class D, class B>
+RegisterAddBaseInit<D,B> AddBaseInit<D,B>::s_regbase;
+#endif
+
+
+
+/**
+ * @brief Helper to get the copy conversion initialized.
+ */
+template <class D, class B>
+struct RegisterAddCopyConversionInit
+{
+  /// Add ourself to the init list.
+  RegisterAddCopyConversionInit();
+
+  /// Init callback: xxx
+  static const BaseInfoBase& doinit();
+};
+
+
+#ifndef __REFLEX__
+/**
+ * @brief Init callback: add the new conversion to the BIB.
+ */
+template <class T, class C>
+const BaseInfoBase& RegisterAddCopyConversionInit<T, C>::doinit()
+{
+  // Look up the BIB.
+  SG::BaseInfoBase* bib =
+    const_cast<SG::BaseInfoBase*> (SG::BaseInfoBase::find (typeid(T)));
+  if (!bib)
+    bib = const_cast<SG::BaseInfoBase*> (&BaseInfo<T>::baseinfo());
+  if (bib) {
+    typedef typename C::target_type target_type;
+    bib->add_copy_conversion (SG::safe_clid<target_type>(),
+                              typeid(target_type),
+                              new C);
+  }
+  return *bib;
+}
+
+
+/**
+ * @brief Add ourself to the init list.
+ */
+template <class T, class C>
+RegisterAddCopyConversionInit<T, C>::RegisterAddCopyConversionInit()
+{
+  BaseInfoBase::addInit(SG::safe_clid<T>(), &typeid(T), doinit);
+}
+#endif
+
+
+/**
+ * @brief Helper to get @c AddBaseInfo initialized.
+ */
+template <class T, class C> struct AddCopyConversionInit {
+  static RegisterAddCopyConversionInit<T, C> s_regbase;
+};
+#ifndef __APPLE__
+template <class T, class C>
+RegisterAddCopyConversionInit<T,C> AddCopyConversionInit<T,C>::s_regbase;
+#endif
+
+
+} // namespace SG
+
diff --git a/Control/SGTools/SGTools/BuiltinsClids.h b/Control/SGTools/SGTools/BuiltinsClids.h
new file mode 100644
index 0000000000000000000000000000000000000000..f478ae7709eac12269b130989591fc818ead8793
--- /dev/null
+++ b/Control/SGTools/SGTools/BuiltinsClids.h
@@ -0,0 +1,33 @@
+///////////////////////// -*- C++ -*- /////////////////////////////
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// BuiltinsClids.h 
+// Header file for CLIDs for C++ builtins
+// Author: S.Binet<binet@cern.ch>
+/////////////////////////////////////////////////////////////////// 
+#ifndef SGTOOLS_BUILTINSCLIDS_H 
+#define SGTOOLS_BUILTINSCLIDS_H 
+
+// STL includes
+#include <string>
+
+// Gaudi includes
+
+// SGTools includes
+#include "SGTools/CLASS_DEF.h"
+
+CLASS_DEF( char ,          81926032 , 1 )
+CLASS_DEF( bool ,         134610868 , 1 )
+CLASS_DEF( int ,          244260744 , 1 )
+CLASS_DEF( unsigned int ,  78410462 , 1 )
+CLASS_DEF( long ,         136869678 , 1 )
+CLASS_DEF( unsigned long , 47413844 , 1 )
+CLASS_DEF( long long ,     16133813 , 1 )
+CLASS_DEF( float ,        225912587 , 1 )
+CLASS_DEF( double ,       239989609 , 1 )
+CLASS_DEF( std::string ,  116449351 , 1 )
+
+#endif // !SGTOOLS_BUILTINSCLIDS_H
diff --git a/Control/SGTools/SGTools/CLASS_DEF.h b/Control/SGTools/SGTools/CLASS_DEF.h
new file mode 100755
index 0000000000000000000000000000000000000000..7f4d90607ee686c6b823b1c4e5d1f6b4fc34271d
--- /dev/null
+++ b/Control/SGTools/SGTools/CLASS_DEF.h
@@ -0,0 +1,102 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef SGTOOLS_CLASS_DEF_H
+#define SGTOOLS_CLASS_DEF_H
+/** @file CLASS_DEF.h
+ *  @brief macros to associate a CLID to a type
+ *
+ *  @author Paolo Calafiura <pcalafiura@lbl.gov>
+ *  $Id: CLASS_DEF.h,v 1.3 2009-01-15 19:07:29 binet Exp $
+ */
+
+#include "SGTools/ClassID_traits.h"
+#include "CxxUtils/unused.h"
+#include <boost/preprocessor/stringize.hpp>
+
+/** @def CLASS_DEF(NAME, CID , VERSION) 
+ *  @brief associate a clid and a version to a type
+ *  eg 
+ *  @code 
+ *  CLASS_DEF(std::vector<Track*>,8901, 1)
+ *  @endcode 
+ *  @param NAME 	type name
+ *  @param CID 		clid
+ *  @param VERSION 	not yet used
+ */
+#define CLASS_DEF(NAME, CID , VERSION)		\
+  template <>					\
+  struct ClassID_traits< NAME > {				 \
+    typedef boost::is_base_and_derived<DataObject, NAME> isDObj_t;	\
+    BOOST_STATIC_CONSTANT(bool, s_isDataObject = isDObj_t::value);	\
+    typedef type_tools::Int2Type<s_isDataObject> is_DataObject_tag;	\
+    typedef type_tools::true_tag has_classID_tag;			\
+    static const CLID& ID() { static CLID c(CID); return  c; }		\
+    static const std::string& typeName() {				\
+      static const std::string s_name = #NAME;				\
+      return s_name;							\
+    }									\
+    static  Athena::PackageInfo packageInfo() {				\
+      static Athena::PackageInfo __pi( BOOST_PP_STRINGIZE(PACKAGE_VERSION_UQ)  ); \
+      return __pi;							\
+    }									\
+    static const std::type_info& typeInfo() {				\
+      return typeid (NAME);						\
+    }									\
+    typedef type_tools::true_tag has_version_tag;			\
+    BOOST_STATIC_CONSTANT(int, s_version = VERSION);			\
+    BOOST_STATIC_CONSTANT(bool, s_isConst = false);                     \
+  };									\
+  namespace detail {							\
+    const bool UNUSED(clidEntry_ ## CID) =                              \
+      CLIDRegistry::addEntry<CID>(ClassID_traits< NAME >::typeName(),	\
+				  ClassID_traits< NAME >::packageInfo(), \
+				  ClassName< NAME >::name());		\
+  } 
+
+
+/** @def CLASS_DEF2(ARG1, ARG2, CID , VERSION) 
+ *  @brief hack to use instead of CLASS_DEF when type name contains a comma ','
+ *  eg
+ *  @code 
+ *    CLASS_DEF2(map<int,string>,8900, 1)
+ *  @endcode 
+ *  @param ARG1         type name (1st part)
+ *  @param ARG2 	type name (2nd part)
+ *  @param CID 		clid
+ *  @param VERSION 	not yet used
+ */
+#define CLASS_DEF2(ARG1, ARG2, CID , VERSION)	\
+  template <>					\
+  struct ClassID_traits< ARG1,ARG2 > {					\
+    typedef boost::is_base_and_derived<DataObject, ARG1, ARG2 > isDObj_t; \
+    BOOST_STATIC_CONSTANT(bool, s_isDataObject = isDObj_t::value);	\
+    typedef type_tools::Int2Type<s_isDataObject> is_DataObject_tag;	\
+    typedef type_tools::true_tag has_classID_tag;			\
+    static const CLID& ID() {						\
+      static CLID c(CID); return  c;					\
+    }									\
+    static const std::string& typeName() {				\
+      static const std::string s_name = #ARG1 "," #ARG2;		\
+      return s_name;							\
+    }									\
+    static const std::type_info& typeInfo() {				\
+      return typeid (ARG1,ARG2);					\
+    }									\
+    static  Athena::PackageInfo packageInfo() {				\
+      return Athena::PackageInfo("Package-00-00-00");			\
+    }									\
+    typedef type_tools::true_tag has_version_tag;			\
+    BOOST_STATIC_CONSTANT(int, s_version = VERSION);			\
+    BOOST_STATIC_CONSTANT(bool, s_isConst = false);                     \
+  };									\
+  namespace detail {							\
+    const bool UNUSED(clidEntry_ ## CID) =                              \
+      CLIDRegistry::addEntry<CID> \
+      (ClassID_traits< ARG1,ARG2 >::typeName(),				\
+       ClassID_traits< ARG1,ARG2 >::packageInfo(),			\
+       ClassName< ARG1,ARG2 >::name());					\
+  } 
+
+#endif // not SGTOOLS_CLASS_DEF_H
diff --git a/Control/SGTools/SGTools/CLIDRegistry.h b/Control/SGTools/SGTools/CLIDRegistry.h
new file mode 100755
index 0000000000000000000000000000000000000000..e0353cb1cd3ea494516daf6fbc93bc3e82665de2
--- /dev/null
+++ b/Control/SGTools/SGTools/CLIDRegistry.h
@@ -0,0 +1,115 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef SGTOOLS_CLIDREGISTRY_H
+# define SGTOOLS_CLIDREGISTRY_H
+/** @file CLIDRegistry.h
+ * @brief  a static registry of CLID->typeName entries. NOT for general use.
+ * Use ClassIDSvc instead.
+ *
+ * @author Paolo Calafiura <pcalafiura@lbl.gov> - ATLAS Collaboration
+ *$Id: CLIDRegistry.h,v 1.2 2009-01-15 19:07:29 binet Exp $
+ */
+
+#include <vector>
+#include <string>
+#include <utility> /* pair */
+#include <boost/tuple/tuple.hpp>
+#include <boost/static_assert.hpp>
+
+/* #define CLIDREG_DEBUG 1 */
+#ifdef CLIDREG_DEBUG
+ #include <iostream> 
+#endif
+
+#include "AthenaKernel/tools/AthenaPackageInfo.h"
+#ifndef BOOST_HAS_STATIC_ASSERT
+# include "CxxUtils/unused.h"
+#endif
+
+namespace detail {
+  /// @name allowed class id range
+  //@{	
+  const unsigned long MINCLID = 256;
+  const unsigned long MAXCLID = 2147483647; ///< 2**31 - 1
+  //@}	
+}
+
+/** @class CLIDRegistry
+ * @brief  a static registry of CLID->typeName entries. NOT for general use.
+ * Use ClassIDSvc instead.
+ */
+class CLIDRegistry {
+private:
+  typedef boost::tuple <unsigned long, 
+			std::string, 
+			Athena::PackageInfo,
+			std::string> tuple_t;
+  typedef std::vector< tuple_t > CLIDRegistryImpl;
+public:
+  typedef CLIDRegistryImpl::const_iterator const_iterator;
+
+  ///to be called by the CLASS_DEFS
+  template <unsigned long CLID>
+  static bool addEntry(const std::string& typeName, 
+		       const Athena::PackageInfo& pkgInfo,
+		       const std::string& typeInfoName); 
+  //    static bool addEntry(unsigned long id, const std::string& typeName);
+
+  /// allowed class id range (backward compatibility)
+  //@{	
+  static const unsigned long MINCLID;
+  static const unsigned long MAXCLID;
+  //@}	
+ 
+  /// registry accessors (used by ClassIDSvc)
+  //@{
+  static const_iterator begin();
+  static const_iterator end(); 
+  /// are there new entries since last call? Does not move the entries ptr
+  static bool hasNewEntries();
+  /// returns an iterator range over the entries added since last time
+  /// newEntries was called
+  static std::pair<const_iterator, const_iterator> newEntries();
+  //@}
+
+private:
+  static CLIDRegistryImpl& registry();
+};
+
+
+//the drudgery below is to issue a compilation error when CLID is
+//out of range
+template <bool x> struct ERROR_CLID_out_of_CLIDRegistry_range;
+template <>       struct ERROR_CLID_out_of_CLIDRegistry_range<true>{};
+
+#ifndef __GCCXML__
+
+//<<<<<< INLINE MEMBER FUNCTIONS                                        >>>>>>
+template <unsigned long CLID>
+bool CLIDRegistry::addEntry(const std::string& typeName, 
+			    const Athena::PackageInfo& pkgInfo,
+			    const std::string& typeInfoName) {
+  //more drudgery
+#ifdef BOOST_HAS_STATIC_ASSERT
+  static_assert (detail::MINCLID <= CLID && CLID <= detail::MAXCLID,
+                 "CLID out of CLIDRegistry range");
+#else
+  UNUSED(typedef ::boost::static_assert_test<
+    sizeof(ERROR_CLID_out_of_CLIDRegistry_range< (bool)(detail::MINCLID <= CLID && CLID <= detail::MAXCLID) >)
+         > BOOST_JOIN(boost_static_assert_typedef_, __LINE__));
+#endif
+
+  registry().push_back(tuple_t(CLID, typeName, pkgInfo, typeInfoName));
+#ifdef CLIDREG_DEBUG
+  std::cerr << "CLIDRegistry::addEntry: for CLID/type " 
+	    << CLID << '/' << typeName << " to registry " <<&registry() 
+	    <<std::endl;
+#endif		
+  return true;
+}
+
+#endif
+
+#endif // SGTOOLS_CLIDREGISTRY_H
diff --git a/Control/SGTools/SGTools/CallBackID.h b/Control/SGTools/SGTools/CallBackID.h
new file mode 100755
index 0000000000000000000000000000000000000000..11df6021bcb47318181a1296bbf93a1a3d1d94d5
--- /dev/null
+++ b/Control/SGTools/SGTools/CallBackID.h
@@ -0,0 +1,65 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef SGTOOLS_CALLBACKID_H
+#define SGTOOLS_CALLBACKID_H
+
+/*****************************************************************************
+ *
+ *  CallBackID.h
+ *  IOVSvc
+ *
+ *  Author: Charles Leggett
+ *  $Id: CallBackID.h,v 1.3 2005-11-08 22:01:30 ssnyder Exp $
+ *
+ *  Provides means to identify a callback function.
+ *
+ *****************************************************************************/
+
+#ifndef ATHENAKERNEL_IOVSVCDEFS_H
+ #include "AthenaKernel/IOVSvcDefs.h"
+#endif
+
+class CallBackID {
+public:
+  CallBackID():m_offset(0),p_obj(0){};
+
+  template<typename T>
+  CallBackID(StatusCode (T::*updF)(IOVSVC_CALLBACK_ARGS), const T *obj) {
+    set(updF,obj);
+  }
+
+  template<typename T>
+  void set(StatusCode (T::*updF)(IOVSVC_CALLBACK_ARGS), const T *obj);
+
+  std::string name() const { return m_name; }
+  std::string objName() const { return m_objName; }
+  int offset() const { return m_offset; }
+  const void* ptr() const { return p_obj; }
+
+  bool operator==(const CallBackID& cb) const {
+    return ( cb.m_offset == m_offset && cb.p_obj == p_obj );
+  }
+  bool operator<(const CallBackID& cb) const {
+    if ( p_obj != cb.p_obj ) {
+      return ( p_obj < cb.p_obj ) ;
+    } else {
+      return ( m_offset < cb.m_offset );
+    }
+  }
+
+private:
+  long m_offset;
+  const void* p_obj;
+
+  std::string m_name;
+  std::string m_objName;
+
+};
+
+#ifndef SGTOOLS_CALLBACKID_ICC
+ #include "SGTools/CallBackID.icc"
+#endif
+
+#endif
diff --git a/Control/SGTools/SGTools/CallBackID.icc b/Control/SGTools/SGTools/CallBackID.icc
new file mode 100755
index 0000000000000000000000000000000000000000..72c251e9588659108fbc765e1ca34b8228720fb7
--- /dev/null
+++ b/Control/SGTools/SGTools/CallBackID.icc
@@ -0,0 +1,56 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef SGTOOLS_CALLBACKID_ICC
+#define SGTOOLS_CALLBACKID_ICC
+
+/*****************************************************************************
+ *
+ *  CallBackID.h
+ *  IOVSvc
+ *
+ *  Author: Charles Leggett
+ *  $Id: CallBackID.icc,v 1.4 2005-11-08 22:01:30 ssnyder Exp $
+ *
+ *  Provides means to identify a callback function.
+ *
+ *****************************************************************************/
+
+#ifndef _CPP_SSTREAM
+ #include <sstream>
+#endif
+#ifndef _STDIO_H
+ #include "stdio.h"
+#endif
+#ifndef GAUDIKERNEL_SYSTEM_H
+ #include "GaudiKernel/System.h"
+#endif
+
+template<typename T>
+void CallBackID::set( StatusCode (T::*updF)(IOVSVC_CALLBACK_ARGS), 
+		      const T *obj)
+{
+  union {
+    StatusCode (T::*updF)(IOVSVC_CALLBACK_ARGS);
+    long i;
+  } u;
+  u.updF = updF;
+
+  p_obj = (void*) obj;
+  m_offset = u.i;
+  
+  // make allowances for various versions of gcc
+  #if (__GNUC__ < 3)
+     m_offset /= 0x10000;
+  #endif
+
+  std::ostringstream ost;
+  ost << std::hex << "[0x" << (long)p_obj << "]+" << m_offset;
+  
+  m_objName = System::typeinfoName(typeid(*obj));
+  m_name = m_objName + ost.str();
+  
+}
+
+#endif
diff --git a/Control/SGTools/SGTools/ClassID_traits.h b/Control/SGTools/SGTools/ClassID_traits.h
new file mode 100755
index 0000000000000000000000000000000000000000..ed282a221fb8ff0519ef113ca18335099d3d076d
--- /dev/null
+++ b/Control/SGTools/SGTools/ClassID_traits.h
@@ -0,0 +1,106 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef SGTOOLS_CLASSID_TRAITS_H
+#define SGTOOLS_CLASSID_TRAITS_H
+/** @file ClassID_traits.h
+ * @brief  a traits class that associates a CLID to a type T
+ * It also detects whether T inherits from Gaudi DataObject
+ *
+ * @author Paolo Calafiura <pcalafiura@lbl.gov> - ATLAS Collaboration
+ * $Id: ClassID_traits.h,v 1.3 2009-01-15 19:07:29 binet Exp $
+ */
+#include <string>
+#include <typeinfo>
+
+#include <boost/config.hpp>
+#include <boost/type_traits/object_traits.hpp>
+#include <boost/concept_check.hpp>
+#include <boost/static_assert.hpp>
+
+#include "GaudiKernel/ClassID.h"
+#include "GaudiKernel/DataObject.h"
+#include "GaudiKernel/System.h"
+
+#include "SGTools/CLIDRegistry.h"
+#include "SGTools/ClassName.h"
+
+#include "AthenaKernel/tools/type_tools.h"
+#include "AthenaKernel/tools/AthenaPackageInfo.h"
+#ifndef BOOST_HAS_STATIC_ASSERT
+# include "CxxUtils/unused.h"
+#endif
+
+
+
+template <bool x> struct ERROR_you_should_use_the_CLASS_DEF_macro_to_define_CLID_and_VERSION;
+template <>       struct ERROR_you_should_use_the_CLASS_DEF_macro_to_define_CLID_and_VERSION<true>{};
+
+///internal use: issues a compilation error when condition B is false
+#ifdef BOOST_HAS_STATIC_ASSERT
+#define MY_STATIC_ASSERT( B ) \
+  static_assert (B, "You should use the CLASS_DEF macro to define CLID and VERSION");
+#else
+#define MY_STATIC_ASSERT( B ) \
+  UNUSED(typedef ::boost::static_assert_test<                           \
+      sizeof(ERROR_you_should_use_the_CLASS_DEF_macro_to_define_CLID_and_VERSION< (bool)( B ) >)>\
+         BOOST_JOIN(boost_static_assert_typedef_, __LINE__))
+#endif
+
+/** @class ClassID_traits
+ * @brief  a traits class that associates a CLID to a type T
+ * It also detects whether T inherits from Gaudi DataObject
+ */
+template <typename T>
+struct ClassID_traits {
+  //default only works for DataObjects
+  typedef boost::is_base_and_derived<DataObject, T> isDObj_t; 
+  ///flags whether T inherits from DataObject
+  BOOST_STATIC_CONSTANT(bool, s_isDataObject = isDObj_t::value); 
+
+  //default traits for class ID assignment
+  typedef type_tools::Int2Type<s_isDataObject> is_DataObject_tag;
+
+  ///the CLID of T
+  static const CLID& ID() { 
+    MY_STATIC_ASSERT(s_isDataObject);
+    return T::classID(); 
+  }
+
+  ///the demangled type name of T
+  static const std::string& typeName() {
+    MY_STATIC_ASSERT(s_isDataObject);
+    static const std::string s_tname = System::typeinfoName(typeid(T));
+    return s_tname;
+  }
+
+  ///the type id of T
+  static const std::type_info& typeId() {
+    MY_STATIC_ASSERT(s_isDataObject);
+    return typeid(T);
+  }
+
+  ///the package name of this CLASSDEF (and BY CONVENTION of the data obj too!)
+  static  Athena::PackageInfo packageInfo() {
+    MY_STATIC_ASSERT(s_isDataObject);
+    return Athena::PackageInfo("Package-00-00-00");
+  }
+
+  typedef type_tools::false_tag has_version_tag;
+  BOOST_STATIC_CONSTANT(int, s_version = 0);
+
+  // Is this is true, these types will automatically be made
+  // const when added to StoreGate.
+  BOOST_STATIC_CONSTANT(bool, s_isConst = false);
+};
+
+#undef MY_STATIC_ASSERT
+
+#endif // not SGTOOLS_CLASSID_TRAITS_H
+
+
+
+
+
+
diff --git a/Control/SGTools/SGTools/ClassName.h b/Control/SGTools/SGTools/ClassName.h
new file mode 100644
index 0000000000000000000000000000000000000000..caa8f052f9503de027935a9df459eedd2c7f2beb
--- /dev/null
+++ b/Control/SGTools/SGTools/ClassName.h
@@ -0,0 +1,45 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: ClassName.h,v 1.1 2009-01-15 19:07:29 binet Exp $
+/**
+ * @file  SGTools/ClassName.h
+ * @author scott snyder
+ * @date Jul 2005
+ * @brief An interface for getting the name of a class as a string.
+ */
+
+
+#ifndef SGTOOLS_CLASSNAME_H
+#define SGTOOLS_CLASSNAME_H
+
+
+#include <string>
+
+
+/**
+ * @brief An interface for getting the name of a class as a string.
+ *
+ * This template class provides an interface for getting the name
+ * of a class as a string.  By default, it uses @c typeinfoName
+ * from @c GaudiKernel, but it may be specialized to override
+ * the behavior for specific classes.
+ */
+template <class T>
+class ClassName
+{
+public:
+  /**
+   * @brief Return the name of class @c T as a string.
+   */
+  static std::string name();
+};
+
+
+#include "SGTools/ClassName.icc"
+
+
+#endif // not SGTOOLS_CLASSNAME_H
diff --git a/Control/SGTools/SGTools/ClassName.icc b/Control/SGTools/SGTools/ClassName.icc
new file mode 100644
index 0000000000000000000000000000000000000000..55e22f24897c17181a457113d36cd1298db54793
--- /dev/null
+++ b/Control/SGTools/SGTools/ClassName.icc
@@ -0,0 +1,85 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: ClassName.icc,v 1.1 2009-01-15 19:07:29 binet Exp $
+/**
+ * @file  DataModel/ClassName.icc
+ * @author scott snyder
+ * @date Jul 2005
+ * @brief An interface for getting the name of a class as a string.
+ *        Implementation file.
+ */
+
+
+#include "GaudiKernel/System.h"
+
+
+/**
+ * @brief Return the name of class @c T as a string.
+ */
+template <class T>
+std::string ClassName<T>::name()
+{
+  return System::typeinfoName (typeid (T));
+}
+
+// /**
+//  * @brief Specialization of @c ClassName for @c std::vector.
+//  *
+//  * This overrides the default implementation of @c ClassName
+//  * to hide @c std::vector's second template parameter.
+//  */
+// #include <vector>
+// template <class T>
+// std::string ClassName<std::vector<T> >::name()
+// {
+//   std::string out = "std::vector<";
+//   out += ClassName<T>::name();
+//   if (out[out.size()-1] == '>')
+//     out += ' ';
+//   out += '>';
+//   return out;
+// }
+
+// /**
+//  * @brief Specialization of @c ClassName for @c std::list.
+//  *
+//  * This overrides the default implementation of @c ClassName
+//  * to hide @c std::list's second template parameter.
+//  */
+// #include <list>
+// template <class T>
+// std::string ClassName<std::list<T> >::name()
+// {
+//   std::string out = "std::list<";
+//   out += ClassName<T>::name();
+//   if (out[out.size()-1] == '>')
+//     out += ' ';
+//   out += '>';
+//   return out;
+// }
+
+// /**
+//  * @brief Specialization of @c ClassName for @c std::map.
+//  *
+//  * This overrides the default implementation of @c ClassName
+//  * to hide @c std::map's 4th template parameter (and optionally the 3rd too)
+//  */
+// #include <map>
+// template <class K, class V, class C>
+// std::string ClassName<std::map<K, V, C> >::name()
+// {
+//   std::string out = "std::map<";
+//   out += ClassName<K>::name()+ "," + ClassName<V>::name();
+//   std::string comp = ClassName<C>::name();
+//   if (comp.size() > 10 && comp.substr(0, 10) != "std::less<") {
+//     out += ","+ClassName<C>::name();
+//   }
+//   if (out[out.size()-1] == '>')
+//     out += ' ';
+//   out += '>';
+//   return out;
+// }
+
+
diff --git a/Control/SGTools/SGTools/DataBucket.h b/Control/SGTools/SGTools/DataBucket.h
new file mode 100755
index 0000000000000000000000000000000000000000..e92da77a4023e7ab121488c89cfc0a9c4881f47d
--- /dev/null
+++ b/Control/SGTools/SGTools/DataBucket.h
@@ -0,0 +1,124 @@
+///////////////////////// -*- C++ -*- /////////////////////////////
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef SGTOOLS_DATABUCKET_H
+#define SGTOOLS_DATABUCKET_H
+
+#include "SGTools/DataBucketBase.h"
+#include "CxxUtils/override.h"
+
+//FIXME CLID is a tdef and can't be forward declared 
+#include "GaudiKernel/ClassID.h"
+#include <memory>
+
+/** @class DataBucket
+ *  @brief a wrapper inheriting from DataObject (via DataBucketBase)
+ *  that takes ownership of a data object to be put in the DataStore
+ *  @author ATLAS Collaboration
+ *  $Id: DataBucket.h,v 1.10 2008-06-25 22:45:49 calaf Exp $
+ **/
+
+namespace SG { 
+  class IRegisterTransient;
+  class CopyConversionBase;
+
+  template <class T> 
+  class DataBucket : public DataBucketBase {
+  
+  public:
+    
+    // CONSTRUCTORS:
+  
+    DataBucket(): m_ptr(0) {}  //needed by the generic converters
+    DataBucket(T* data);                 
+#if __cplusplus > 201100
+    DataBucket(std::unique_ptr<T> data);
+#endif
+  
+    // DESTRUCTOR:
+  
+    virtual ~DataBucket();
+  
+    // DATAOBJECT METHODS --- FIXME not virtual! derived buckets?
+    const CLID& clID() const;  
+    static const CLID& classID();
+
+    // return the pointer as a void*
+    virtual void* object() ATH_OVERRIDE { return m_ptr; }
+
+    // Serialize the object for reading
+    //  StreamBuffer& serialize(StreamBuffer& s);
+    // Serialize the object for writing
+    //  StreamBuffer& serialize(StreamBuffer& s)  const;
+  
+  
+
+    // AUTOMATIC CONVERSION OF TYPES
+    operator T*()                 { return ptr(); } //FIXME can we do without?
+    operator const T*() const     { return cptr(); }
+
+    /**
+     * @brief Return the contents of the @c DataBucket,
+     *        converted to type given by @a clid.  Note that only
+     *        derived->base conversions are allowed here.
+     * @param clid The class ID to which to convert.
+     * @param irt To be called if we make a new instance.
+     * @param isConst True if the object being converted is regarded as const.
+     */
+    virtual void* cast (CLID clid,
+                        IRegisterTransient* irt = 0,
+                        bool isConst = true) const ATH_OVERRIDE;
+    
+
+    /**
+     * @brief Return the contents of the @c DataBucket,
+     *        converted to type given by @a std::type_info.  Note that only
+     *        derived->base conversions are allowed here.
+     * @param clid The @a std::type_info of the type to which to convert.
+     * @param irt To be called if we make a new instance.
+     * @param isConst True if the object being converted is regarded as const.
+     */
+    virtual void* cast (const std::type_info& tinfo,
+                        IRegisterTransient* irt = 0,
+                        bool isConst = true) const ATH_OVERRIDE;
+
+    /**
+     * @brief Return a new @c DataBucket whose payload has been cloned from the
+     *        original one.
+     */
+    virtual DataBucket* clone() const ATH_OVERRIDE;
+
+    /**
+     * @brief Give up ownership of the  @c DataBucket contents.
+     *        This leaks the contents and it is useful mainly for error handling.
+     */
+    virtual void relinquish() ATH_OVERRIDE{ m_ptr=0;} //LEAKS m_ptr
+
+    /**
+     * If the held object derives from @c ILockable, call @lock() on it.
+     */
+    virtual void lock() ATH_OVERRIDE;
+
+
+  protected:
+    T* ptr() { return m_ptr; }
+    const T* cptr() const { return m_ptr; }
+
+  private:
+    T* m_ptr;  //we own the thing now!
+
+    /// Objects made by copy conversion.
+    typedef std::pair<const CopyConversionBase*, void*> ent_t;
+    typedef std::vector<ent_t> vec_t;
+    mutable vec_t m_cnvcopies;
+
+    DataBucket (const DataBucket&);
+    DataBucket& operator= (const DataBucket&);
+  };
+} //end namespace SG  
+#include "SGTools/DataBucket.icc"
+
+#endif // SGTOOLS_DATABUCKET_H
diff --git a/Control/SGTools/SGTools/DataBucket.icc b/Control/SGTools/SGTools/DataBucket.icc
new file mode 100755
index 0000000000000000000000000000000000000000..62c04feb1d8320aa989a1672d3491d5c3ccfcc4b
--- /dev/null
+++ b/Control/SGTools/SGTools/DataBucket.icc
@@ -0,0 +1,261 @@
+///////////////////////// -*- C++ -*- /////////////////////////////
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef SGTOOLS_DATABUCKET_H
+#include "SGTools/DataBucket.h"
+#endif
+
+#include <boost/type_traits/cv_traits.hpp>
+#include <boost/type_traits/transform_traits.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_abstract.hpp>
+#include <boost/type_traits/has_trivial_copy.hpp>
+
+#include "SGTools/ClassID_traits.h"
+#include "SGTools/BaseInfo.h"
+#include "SGTools/IRegisterTransient.h"
+#include "AthenaKernel/ILockable.h"
+
+#if __cplusplus > 201100
+# include <type_traits>
+namespace SG_STD_OR_BOOST = std;
+#else
+# include "boost/type_traits/is_polymorphic.hpp"
+namespace SG_STD_OR_BOOST = boost;
+#endif
+
+
+
+// Some helper functions.
+namespace SG {
+
+
+// If T is a DataObject, increment its reference count.
+// The second parameter tells whether or not T is a DataObject.
+template <class T>
+void db_maybe_ref (T*, type_tools::false_tag)
+{
+}
+template <class T>
+void db_maybe_ref (T* ptr, type_tools::true_tag)
+{
+  ptr->addRef();
+}
+
+
+// Release the pointer PTR.
+// If T is a DataObject, then decrement the reference count;
+// otherwise, just delete it.
+// The second parameter tells whether or not T is a DataObject.
+template <class T>
+void db_free_ptr (T* ptr, type_tools::false_tag)
+{
+  //  std::cout << "db_free_ptr: deleting ptr @" << ptr << " of type " << ClassID_traits<T>::typeName() << std::endl;
+  delete ptr;
+}
+template <class T>
+void db_free_ptr (T* ptr, type_tools::true_tag)
+{
+  //  std::cout << "db_free_ptr: releasing ptr @" << ptr << " of type " << ClassID_traits<T>::typeName() << std::endl;
+  ptr->release();
+}
+
+// if T is abstract just return NULL and let clients deal with that
+template <typename T>
+SG::DataBucket<T>* db_clone_ptr (T*, boost::false_type)
+{ return NULL; }
+
+// else use the copy constructor
+template <typename T>
+SG::DataBucket<T>* db_clone_ptr (T* ptr, boost::true_type)
+{ return new SG::DataBucket<T>( new T(*ptr) ); }
+
+} // namespace SG
+
+
+///////////////////////////////////////////////////////////////////////////////
+// CONSTRUCTORS
+///////////////////////////////////////////////////////////////////////////////
+template <typename T> 
+SG::DataBucket<T>::DataBucket(T* data)
+  : m_ptr(data)
+{
+  // If T is a DataObject, increase the refcount.
+  typedef typename ClassID_traits<T>::is_DataObject_tag tag;
+  if (m_ptr)
+    SG::db_maybe_ref (m_ptr, tag());
+}
+
+#if __cplusplus > 201100
+template <typename T> 
+SG::DataBucket<T>::DataBucket(std::unique_ptr<T> data)
+  : m_ptr(data.release())
+{
+  // If T is a DataObject, increase the refcount.
+  typedef typename ClassID_traits<T>::is_DataObject_tag tag;
+  if (m_ptr)
+    SG::db_maybe_ref (m_ptr, tag());
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// DATAOBJECT
+///////////////////////////////////////////////////////////////////////////////
+template <typename T> 
+const CLID& SG::DataBucket<T>::clID() const {return classID();}  
+
+template <typename T> 
+const CLID& SG::DataBucket<T>::classID() { 
+  typedef typename ::boost::remove_pointer<T>::type BareTp;
+  typedef typename ::boost::remove_const<BareTp>::type BareT;
+  return ClassID_traits<BareT>::ID();
+}
+
+
+/**
+ * @brief Return the contents of the @c DataBucket,
+ *        converted to type given by @a clid.  Note that only
+ *        derived->base conversions are allowed here.
+ * @param clid The class ID to which to convert.
+ * @param irt To be called if we make a new instance.
+ * @param isConst True if the object being converted is regarded as const.
+ */
+template <typename T> 
+void*
+SG::DataBucket<T>::cast (CLID clid,
+                         IRegisterTransient* irt /*= 0*/,
+                         bool isConst /*=true*/) const
+{
+  void* ret = SG::BaseInfo<T>::cast (m_ptr, clid);
+  if (ret || !isConst)
+    return ret;
+
+  // Is there a copy conversion available?
+  const CopyConversionBase* cc = SG::BaseInfo<T>::baseinfo().copy_conversion (clid);
+  if (cc) {
+    vec_t::iterator end = m_cnvcopies.end();
+    for (vec_t::iterator it = m_cnvcopies.begin(); it != end; ++it) {
+      if (cc == it->first) {
+        cc->convertUntyped (m_ptr, it->second);
+      }
+      return it->second;
+    }
+
+    void* newcont = cc->create();
+    if (newcont) {
+      cc->convertUntyped (m_ptr, newcont);
+      m_cnvcopies.push_back (std::make_pair (cc, newcont));
+      irt->registerTransient (newcont);
+    }
+    return newcont;
+  }
+
+  return 0;
+}
+
+
+/**
+ * @brief Return the contents of the @c DataBucket,
+ *        converted to type given by @a std::type_info.  Note that only
+ *        derived->base conversions are allowed here.
+ * @param clid The @a std::type_info of the type to which to convert.
+ * @param irt To be called if we make a new instance.
+ * @param isConst True if the object being converted is regarded as const.
+ */
+template <typename T> 
+void* SG::DataBucket<T>::cast (const std::type_info& tinfo,
+                               IRegisterTransient* irt /*= 0*/,
+                               bool isConst /*= true*/) const
+{
+  void* ret = SG::BaseInfo<T>::cast (m_ptr, tinfo);
+  if (ret || !isConst)
+    return ret;
+
+  // Is there a copy conversion available?
+  const CopyConversionBase* cc = SG::BaseInfo<T>::baseinfo().copy_conversion (tinfo);
+  if (cc) {
+    vec_t::iterator end = m_cnvcopies.end();
+    for (vec_t::iterator it = m_cnvcopies.begin(); it != end; ++it) {
+      if (cc == it->first) {
+        cc->convertUntyped (m_ptr, it->second);
+      }
+      return it->second;
+    }
+
+    void* newcont = cc->create();
+    if (newcont) {
+      cc->convertUntyped (m_ptr, newcont);
+      m_cnvcopies.push_back (std::make_pair (cc, newcont));
+      irt->registerTransient (newcont);
+    }
+    return newcont;
+  }
+
+  return 0;
+}
+
+/**
+ * @brief Return a new @c DataBucket whose payload has been cloned from the
+ *        original one.
+ */
+template <typename T>
+SG::DataBucket<T>* SG::DataBucket<T>::clone() const
+{ 
+  if (!m_ptr) { return NULL; }
+
+  typedef 
+    boost::integral_constant< bool, !::boost::is_abstract<T>::value &&
+                                     ::boost::has_trivial_copy<T>::value >
+    truth_type_t;
+  return SG::db_clone_ptr( m_ptr, truth_type_t() );
+}
+
+template <typename T> 
+SG::DataBucket<T>::~DataBucket()
+{
+  // Delete any copies.
+  vec_t::iterator end = m_cnvcopies.end();
+  for (vec_t::iterator it = m_cnvcopies.begin(); it != end; ++it) {
+    it->first->destroy (it->second);
+  }
+
+  // Either delete m_ptr or decrement the refcount,
+  // depending on whether or not T is a DataObject.
+  typedef typename ClassID_traits<T>::is_DataObject_tag tag;
+  if (m_ptr)
+    SG::db_free_ptr(m_ptr, tag());
+}
+
+
+namespace {
+
+
+template <class T>
+void call_lock (T* p, SG_STD_OR_BOOST::true_type)
+{
+  ILockable* l = dynamic_cast<ILockable*> (p);
+  if (l) l->lock();
+}
+
+
+template <class T>
+void call_lock (T*, SG_STD_OR_BOOST::false_type)
+{
+}
+
+
+} // anonymous namespace
+
+
+/**
+ * If the held object derives from @c ILockable, call @lock() on it.
+ */
+template <class T>
+void SG::DataBucket<T>::lock()
+{
+  call_lock (m_ptr, typename SG_STD_OR_BOOST::is_polymorphic<T>::type());
+}
+
diff --git a/Control/SGTools/SGTools/DataBucketBase.h b/Control/SGTools/SGTools/DataBucketBase.h
new file mode 100755
index 0000000000000000000000000000000000000000..40c7006973d67d48f50dc8cce4b992ccdfbd1d1e
--- /dev/null
+++ b/Control/SGTools/SGTools/DataBucketBase.h
@@ -0,0 +1,92 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef SGTOOLS_DATABUCKETBASE_H
+#define SGTOOLS_DATABUCKETBASE_H
+
+/** @class DataBucketBase 
+ * @brief A non-templated base class for DataBucket, allows to access the
+ * transient object address as a void*
+ *  @author ATLAS Collaboration
+ *  $Id: DataBucketBase.h,v 1.7 2008-05-30 22:58:46 calaf Exp $
+ **/
+
+
+#ifndef GAUDIKERNEL_DATAOBJECT_H
+ #include "GaudiKernel/DataObject.h"
+#endif
+#include <typeinfo>
+
+namespace SG {
+  class IRegisterTransient;
+}
+
+class DataBucketBase : public DataObject
+{
+
+ public:
+
+  DataBucketBase() { };
+  virtual ~DataBucketBase() { };
+  virtual void* object() = 0;
+
+  /**
+   * @brief Return the contents of the @c DataBucket,
+   *        converted to type @a T.  Note that only
+   *        derived->base conversions are allowed here.
+   *        @a T must have a valid Class ID for this to work.
+   * @param irt To be called if we make a new instance.
+   * @param isConst True if the object being converted is regarded as const.
+   */
+  template <class T> T* cast (SG::IRegisterTransient* irt = 0,
+                              bool isConst = true) const;
+
+  /**
+   * @brief Return the contents of the @c DataBucket,
+   *        converted to type given by @a clid.  Note that only
+   *        derived->base conversions are allowed here.
+   * @param clid The class ID to which to convert.
+   * @param irt To be called if we make a new instance.
+   * @param isConst True if the object being converted is regarded as const.
+   */
+  virtual void* cast (CLID clid,
+                      SG::IRegisterTransient* irt = 0,
+                      bool isConst = true) const = 0;
+
+  /**
+   * @brief Return the contents of the @c DataBucket,
+   *        converted to type given by @a std::type_info.  Note that only
+   *        derived->base conversions are allowed here.
+   * @param clid The @a std::type_info of the type to which to convert.
+   * @param irt To be called if we make a new instance.
+   * @param isConst True if the object being converted is regarded as const.
+   */
+  virtual void* cast (const std::type_info& tinfo,
+                      SG::IRegisterTransient* irt = 0,
+                      bool isConst = true) const = 0;
+
+  /**
+   * @brief Return a new @c DataBucket whose payload has been cloned from the
+   *        original one.
+   */
+  virtual DataBucketBase* clone() const = 0;
+
+  /**
+   * @brief Give up ownership of the  @c DataBucket contents.
+   *        This leaks the contents and it is useful mainly for error handling.
+   */
+  virtual void relinquish() = 0;
+
+  /**
+   * If the held object derives from @c ILockable, call @lock() on it.
+   */
+  virtual void lock() = 0;
+};
+
+
+#include "SGTools/DataBucketBase.icc"
+
+
+#endif
+
diff --git a/Control/SGTools/SGTools/DataBucketBase.icc b/Control/SGTools/SGTools/DataBucketBase.icc
new file mode 100755
index 0000000000000000000000000000000000000000..38f59c4d07d1c3bd246a3f0705181b1f7d3c96a6
--- /dev/null
+++ b/Control/SGTools/SGTools/DataBucketBase.icc
@@ -0,0 +1,35 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: DataBucketBase.icc,v 1.3 2008-04-08 16:05:32 ssnyder Exp $
+/**
+ * @file  SGTools/DataBucketBase.icc
+ * @author scott snyder
+ * @date Nov 2005
+ * @brief A non-templated base class for DataBucket, allows to access the
+ *        transient object address as a void*
+ *        Implementation file.
+ */
+
+#include "SGTools/ClassID_traits.h"
+#include "boost/type_traits/remove_const.hpp"
+#include <typeinfo>
+
+
+/**
+ * @brief Return the contents of the @c DataBucket,
+ *        converted to type @a T.  Note that only
+ *        derived->base conversions are allowed here.
+ *        @a T must have a valid Class ID for this to work.
+ * @param irt To be called if we make a new instance.
+ * @param isConst True if the object being converted is regarded as const.
+ */
+template <class T>
+T* DataBucketBase::cast (SG::IRegisterTransient* irt /*= 0*/,
+                         bool isConst /*= true*/) const
+{
+  return reinterpret_cast<T*>
+    (cast (typeid (typename boost::remove_const<T>::type), irt, isConst));
+}
+
diff --git a/Control/SGTools/SGTools/DataBucketTraitFwd.h b/Control/SGTools/SGTools/DataBucketTraitFwd.h
new file mode 100644
index 0000000000000000000000000000000000000000..8a182bc3169e848a1b13da38560754e230bd2ed3
--- /dev/null
+++ b/Control/SGTools/SGTools/DataBucketTraitFwd.h
@@ -0,0 +1,36 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: DataBucketTraitFwd.h,v 1.2 2008-04-08 16:05:32 ssnyder Exp $
+
+/**
+ * @file  SGTools/DataBucketTrait.h
+ * @author scott snyder
+ * @date Mar, 2008
+ * @brief Forward declaration of DataBucketTrait template.
+ */
+
+
+#ifndef SGTOOLS_DATABUCKETTRAITFWD_H
+#define SGTOOLS_DATABUCKETTRAITFWD_H
+
+
+namespace SG {
+
+
+  /**
+   * @brief Metafunction to find the proper @c DataBucket class for @c T.
+   *
+   * See in Storable_conversions.h for full documentation.
+   */
+  template <class T, class U = T>
+  struct DataBucketTrait;
+
+
+} // namespace SG
+
+
+#endif // not SGTOOLS_DATABUCKETTRAITFWD_H
diff --git a/Control/SGTools/SGTools/DataHandleBase.h b/Control/SGTools/SGTools/DataHandleBase.h
new file mode 100644
index 0000000000000000000000000000000000000000..35bd0eb7bb51f39b3a34055c54201a262466f3bd
--- /dev/null
+++ b/Control/SGTools/SGTools/DataHandleBase.h
@@ -0,0 +1,127 @@
+///////////////////////// -*- C++ -*- /////////////////////////////
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// DataHandleBase.h 
+// Header file for class DataHandleBase
+// Author: S.Binet<binet@cern.ch>
+/////////////////////////////////////////////////////////////////// 
+#ifndef SGTOOLS_DATAHANDLEBASE_H
+#define SGTOOLS_DATAHANDLEBASE_H 1
+
+// STL includes
+#include <string>
+
+// fwk includes
+#include "AthenaKernel/IProxyDict.h"
+#include "AthenaKernel/IResetable.h"
+
+// SGTools includes
+#include "SGTools/DataProxy.h"
+#include "SGTools/ProxyMap.h"
+
+// Forward declaration
+
+
+/**
+ * @class DataHandleBase 
+ * @brief an iterator over instances of a given type in an @c IProxyDict (such
+ * as StoreGateSvc). It d-casts and caches locally the pointed-at object, to 
+ * speed-up subsequent accesses.
+ * It can be reset by the store for asynchronous updates (IOVSvc)
+ */
+class DataHandleBase : public IResetable
+{ 
+
+  /////////////////////////////////////////////////////////////////// 
+  // Public typedefs: 
+  /////////////////////////////////////////////////////////////////// 
+public: 
+  typedef std::string ID_type;
+
+  /////////////////////////////////////////////////////////////////// 
+  // Public methods: 
+  /////////////////////////////////////////////////////////////////// 
+public: 
+
+  /// Default constructor: 
+  DataHandleBase();
+
+  /// Copy constructor: 
+  DataHandleBase( const DataHandleBase& rhs );
+
+  /// Assignment operator: 
+  DataHandleBase& operator=( const DataHandleBase& rhs ); 
+
+  /// Constructor with parameters: 
+
+  DataHandleBase(SG::DataProxy* proxy); ///< 
+  DataHandleBase(const SG::ConstProxyIterator& itr1,
+                 const SG::ConstProxyIterator& itr2);
+
+  /// Destructor: 
+  virtual ~DataHandleBase(); 
+
+  /////////////////////////////////////////////////////////////////// 
+  // Const methods: 
+  ///////////////////////////////////////////////////////////////////
+
+  /// \name validity checks
+  //@{
+  bool isConst() const;
+  bool isInitialized() const;    ///<weaker test but it does not touch the disk!
+  bool isSet() const { return isInitialized(); }
+  //@}
+
+  /// Get the key string with which the current object was stored.
+  const std::string& key() const;
+
+  StatusCode setState(SG::DataProxy* proxy) const;
+  StatusCode setState(IProxyDict* store, const ID_type& name) const;
+
+  // Note: itr1 may be modified!
+  StatusCode setState(SG::ConstProxyIterator& itr1,
+                      const SG::ConstProxyIterator& itr2) const;
+
+  /// the CLID of the object we are bound to
+  virtual CLID clid() const =0;
+
+  ///get the data object key (ID)
+  ID_type ID() const { return isInitialized() ? m_proxy->name() : "NONE"; }
+
+  /////////////////////////////////////////////////////////////////// 
+  // Non-const methods: 
+  /////////////////////////////////////////////////////////////////// 
+
+  StatusCode setState(SG::DataProxy* proxy);
+  StatusCode setState(IProxyDict* store, const ID_type& name);
+
+  /////////////////////////////////////////////////////////////////// 
+  // Protected data: 
+  /////////////////////////////////////////////////////////////////// 
+protected: 
+
+  /// iterator pointing at the beginning of the range of proxies
+  mutable SG::ConstProxyIterator m_itr;
+
+  /// iterator pointing at the end of the range of proxies
+  mutable SG::ConstProxyIterator m_itrEnd;
+
+  /// the proxy holding the object we are bound to
+  mutable SG::DataProxy* m_proxy;
+
+  /// use the proxy-iterator or just the proxy ?
+  mutable bool m_useItr;
+
+}; 
+
+/////////////////////////////////////////////////////////////////// 
+// Inline methods: 
+/////////////////////////////////////////////////////////////////// 
+//std::ostream& operator<<( std::ostream& out, const DataHandleBase& o );
+
+
+
+#endif //> !SGTOOLS_DATAHANDLEBASE_H
diff --git a/Control/SGTools/SGTools/DataProxy.h b/Control/SGTools/SGTools/DataProxy.h
new file mode 100755
index 0000000000000000000000000000000000000000..abd00db60632ddb5e0fc433c0f6d331b88afbbff
--- /dev/null
+++ b/Control/SGTools/SGTools/DataProxy.h
@@ -0,0 +1,261 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef SGTOOLS_DATAPROXY_H
+#define SGTOOLS_DATAPROXY_H
+
+// includes
+#include <string>
+#include <set>
+#include <list>
+#include <typeinfo>
+#include "GaudiKernel/IRegistry.h"
+#include "GaudiKernel/ClassID.h"
+#include "AthenaKernel/getMessageSvc.h" /*Athena::IMessageSvcHolder*/
+#include "SGTools/TransientAddress.h"
+#include "SGTools/IRegisterTransient.h"
+#include "SGTools/exceptions.h"
+
+
+// forward declarations:
+class DataObject;
+class IConversionSvc;
+class IResetable;
+class IProxyDictWithPool;
+
+/** @class DataProxy 
+ *  @brief DataProxy provides the registry services for StoreGate
+ *  @author ATLAS Collaboration
+ *  $Id: DataProxy.h,v 1.11 2008-07-14 22:16:25 calaf Exp $
+ **/
+
+namespace SG {
+  class T2pMap;
+
+  class DataProxy : public IRegistry, public IRegisterTransient
+  {
+
+  public:
+    enum ErrNo {ALLOK, NOCNVSVC, NOIOA, CNVFAILED, T2PREGFAILED, NERRORS};
+    //FIXME private typedef IRegistry::name_type name_type;
+    //FIXME private typedef IRegistry::id_type id_type;
+    typedef std::string name_type;
+    typedef std::string id_type;
+    typedef TransientAddress::TransientClidSet CLIDCont_t;
+    typedef TransientAddress::TransientAliasSet AliasCont_t;
+
+    // Constructors
+    DataProxy();                      // default constructor
+
+    ///build from TransientAddress
+    DataProxy(TransientAddress* tAddr, 
+	      IConversionSvc* pDataLoader,
+	      bool constFlag=false, bool resetOnly=true);
+
+    ///build from DataObject
+    DataProxy(DataObject* dObject, 
+	      TransientAddress* tAddr,
+	      bool constFlag=false, bool resetOnly=true);
+
+    // Destructor
+    virtual ~DataProxy();
+
+    ///\name IRegistry implementation
+    //@{
+    /// Add reference to object
+    virtual unsigned long addRef();
+
+    /// release reference to object
+    virtual unsigned long release();
+
+    /// return refCount
+    unsigned long refCount() const;
+
+    /// Retrieve data object key == string
+    virtual const name_type& name() const { return m_tAddress->name(); }
+
+    /// Retrieve data object key == string
+    /// duplicated for Gaudi folks does same as name()
+    virtual const id_type& identifier() const {return m_tAddress->name();}
+
+    /// Retrieve DataObject
+    virtual DataObject* object() const      { return m_dObject; }
+
+    /// set an IOpaqueAddress
+    virtual void setAddress(IOpaqueAddress* ioa);
+
+    /// Retrieve IOpaqueAddress
+    virtual IOpaqueAddress* address() const { return m_tAddress->address(); } 
+
+    /// set DataSvc (Gaudi-specific); do nothing for us
+    virtual IDataProviderSvc* dataSvc() const { return 0; }
+    //@}
+
+    /// Retrieve TransientAddress
+    virtual TransientAddress* transientAddress() const { return m_tAddress; }
+
+    /// access set of proxy aliases
+    const AliasCont_t& alias() const { return m_tAddress->alias(); }
+
+    /// Other methods of DataProxy (not in Interface IRegistry):
+
+    /// Reset DataObject and IOpaqueAddress:
+    void reset();
+
+    ///release or reset according to resetOnly flag
+    ///If force is true, then always release.
+    bool requestRelease(bool force = false);
+
+    /// am I valid?
+    bool isValid() const;
+
+    /// is the address valid?
+    bool isValidAddress() const;
+
+    /// is the object valid?
+    bool isValidObject() const;
+
+    /// set DataObject
+    void setObject(DataObject* obj);
+
+    /// Access DataObject on-demand using conversion service
+    ///@throws runtime_error when converter fails
+    DataObject* accessData();
+
+    ErrNo errNo() const { return m_errno; }
+ 
+    /// Retrieve clid
+    CLID clID() const { return m_tAddress->clID(); }
+
+    /// Retrieve storage type
+    unsigned char svcType() const { return m_storageType; }
+
+    /// Check if it is a const object
+    bool isConst() const { return m_const; }
+
+
+    /**
+     * @brief Mark this object as const.  (Lock the object.)
+     *
+     * If the object held that derives from @c ILockable, then we also
+     * call @c lock on the object.
+     */
+    void setConst();
+
+
+    /// set the reset only flag: Clear Store will reset and not delete.
+    void resetOnly(const bool& flag) { m_resetFlag = flag; }
+
+    /// Check reset only:
+    const bool& isResetOnly() const { return m_resetFlag; }
+
+    bool bindHandle(IResetable* ir);
+    void unbindHandle(IResetable* ir);
+
+    /// The following kept temporarily for backward compatibility:
+    const CLIDCont_t& transientID() const {return m_tAddress->transientID();}  
+
+    // cache the t2p
+    void setT2p(T2pMap* t2p);
+
+    /**
+     * @brief Register a transient object in a t2p map.
+     * @param trans The object to register.
+     *
+     * (@c IRegisterTransient interface.)
+     */
+    virtual void registerTransient (void* p);
+
+    /// Set the store of which we're a part.
+    void setStore (IProxyDictWithPool* store) { m_store = store; }
+
+    /// Return the store of which we're a part.
+    IProxyDictWithPool* store() const { return m_store; }
+
+  private:
+    DataProxy(const DataProxy&);
+    DataProxy& operator=(const DataProxy&);
+
+    TransientAddress* m_tAddress;
+
+    unsigned long m_refCount;
+
+    DataObject* m_dObject;
+    IConversionSvc* m_dataLoader;
+
+    /// Is the proxy currently const?
+    bool m_const;
+    /// Was the proxy created as const?
+    bool m_origConst;
+
+    unsigned char m_storageType;
+
+    ///reset and not delete: default is true
+    bool m_resetFlag;        
+
+    /// list of bound DataHandles
+    std::list<IResetable*> m_handles;
+
+    T2pMap* m_t2p;
+    Athena::IMessageSvcHolder m_ims;
+    
+    /// errno-style error code for accessData
+    enum ErrNo m_errno;
+
+    /// The store of which we are a part.
+    IProxyDictWithPool* m_store;
+
+    /// reset the bound DataHandles
+    void resetBoundHandles();
+
+    /**
+     * @brief Lock the data object we're holding, if any.
+     */
+    void lock();
+  };
+
+  ///cast the proxy into the concrete data object it proxies
+  //@{
+  template<typename DATA>
+  DATA* DataProxy_cast(DataProxy* proxy);
+
+  ///const pointer version of the cast
+  template<typename DATA>
+  const DATA* DataProxy_cast(const DataProxy* proxy)
+  {
+    return DataProxy_cast<DATA>(const_cast<DataProxy*>(proxy));
+  }
+
+  ///const ref version of the cast. @throws SG::ExcBadDataProxyCast.
+  template<typename DATA>
+  DATA DataProxy_cast(const DataProxy& proxy)
+  {
+    const DATA* result = DataProxy_cast<DATA>(&proxy);
+    if (!result) SG::throwExcBadDataProxyCast(proxy.clID(), typeid(DATA));
+    return *result;
+  }
+
+  /**
+   * @brief Try to get the pointer back from a @a DataProxy,
+   *        converted to be of type @a clid.
+   * @param proxy The @a DataProxy.
+   * @param clid The ID of the class to which to convert.
+   *
+   * Only works if the held object is a @a DataBucket.
+   * Returns 0 on failure,
+   */
+  void* DataProxy_cast(DataProxy* proxy, CLID clid);
+  //@}
+
+} //end namespace SG
+
+#include "SGTools/DataProxy.icc"
+
+#endif // SGTOOLS_DATAPROXY
+
+
+
+
diff --git a/Control/SGTools/SGTools/DataProxy.icc b/Control/SGTools/SGTools/DataProxy.icc
new file mode 100755
index 0000000000000000000000000000000000000000..bd96b242d153fad4a4083474ed2056506eb6e070
--- /dev/null
+++ b/Control/SGTools/SGTools/DataProxy.icc
@@ -0,0 +1,98 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/***************************************************************************
+ implementation of DataProxy_cast operator
+ -----------------------------------------
+ ATLAS Collaboration
+ ***************************************************************************/
+
+// $Id: DataProxy.icc,v 1.6 2008-07-14 22:16:25 calaf Exp $
+
+//<<<<<< INCLUDES                                                       >>>>>>
+#include "SGTools/DataBucketBase.h"
+#include "SGTools/ClassID_traits.h"
+#include "SGTools/StorableConversions.h"
+#ifndef NDEBUG
+#  include "AthenaKernel/getMessageSvc.h"
+#  include "GaudiKernel/MsgStream.h"
+#endif
+
+
+class DataObject;
+
+template <typename DATA>
+DATA* SG::DataProxy_cast(SG::DataProxy* proxy) {
+  DATA* result(0);
+
+  if (0 != proxy && proxy->isValid()) {
+    DataObject* pObject(proxy->accessData());
+
+    if (0 != pObject) {
+      const CLID& dataID(ClassID_traits<DATA>::ID());
+      result = SG::Storable_cast<DATA>(pObject, true, proxy, proxy->isConst());
+      if (0 == result) { 
+	//if result is 0, probably DATA is neither the type the object was
+	// stored with, nor it inherits from it. 
+	// Before giving up let's check its transient CLIDs
+	DataBucketBase* db(0);
+	if (proxy->transientAddress()->transientID(dataID) &&
+	    0 != (db = dynamic_cast<DataBucketBase*>(pObject)) )
+        {
+	  //it is a symlink after all. Let's hard cast and keep our fingers Xed
+          // But first: if this is a non-const proxy, then the cast
+          // may have failed because it needed to go via a copying conversion
+          // that's not allowed for non-const objects.  So try the conversion
+          // again as const; if that works, then don't do the hard cast.
+          if (!proxy->isConst() &&
+              SG::Storable_cast<DATA>(pObject, true, proxy, true) != 0)
+          {
+#ifndef NDEBUG
+            MsgStream gLog(Athena::getMessageSvc(), "SG::DataProxy_cast");
+            gLog << MSG::WARNING 
+                 << "Request for a non-const object via copying conversion; "
+                 << "requested CLID = " << dataID 
+                 << ", proxy primary ID is " << proxy->clID() << endreq   ;
+#endif
+          }
+          else {
+            // ok, hard cast.
+            result = static_cast<DATA*>(db->object());
+          }
+	}
+        else { 
+#ifndef NDEBUG
+	  MsgStream gLog(Athena::getMessageSvc(), "SG::DataProxy_cast");
+	  gLog << MSG::WARNING 
+	       << "Request for an invalid object; requested CLID = " 
+	       << dataID 
+	       << ", proxy primary ID is " << proxy->clID() << endreq   ;
+#endif
+	} //try symlink
+      } //result 0
+    } else { // invalid pObject
+#ifndef NDEBUG
+      MsgStream gLog(Athena::getMessageSvc(), "SG::DataProxy_cast");
+      gLog << MSG::WARNING 
+	   << "this proxy " << MSG::hex << proxy
+	   << MSG::dec << " has a NULL data object ptr" << endreq;
+#endif
+    }
+  } else {//	invalid proxy
+#if 0
+#ifndef NDEBUG
+    MsgStream gLog(Athena::getMessageSvc(), "SG::DataProxy_cast");
+      gLog << MSG::WARNING 
+	   << "this proxy " << MSG::hex << proxy
+	   << MSG::dec << " [" << proxy->clID() << "/" << proxy->name()
+           << "] is in an invalid state" << endreq;
+#endif
+#endif
+  }
+  return result;
+}
+
+
diff --git a/Control/SGTools/SGTools/DataStore.h b/Control/SGTools/SGTools/DataStore.h
new file mode 100755
index 0000000000000000000000000000000000000000..a0349765d6e72c32d66720fd01ae761408d5889e
--- /dev/null
+++ b/Control/SGTools/SGTools/DataStore.h
@@ -0,0 +1,212 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef STOREGATE_DATASTORE_H
+#define STOREGATE_DATASTORE_H
+/** The Transient Store 
+ *
+ * \author ATLAS Collaboration
+ **/
+
+
+#include "SGTools/ProxyMap.h"
+#include "SGTools/T2pMap.h"
+#include "SGTools/IProxyDictWithPool.h"
+#include "AthenaKernel/DefaultKey.h"
+#include "AthenaKernel/IProxyRegistry.h"
+#include "CxxUtils/unordered_map.h"
+#include "GaudiKernel/ClassID.h"
+#include "GaudiKernel/StatusCode.h"
+#include <boost/array.hpp>
+#include <boost/type_traits/transform_traits.hpp>
+#include <exception>
+#include <list>
+#include <vector>
+#include <map>
+#include <string>
+#include <typeinfo> /*typeid*/
+#include <utility>  /*std::pair*/
+
+
+class ISvcLocator;
+class ISGAudSvc;
+class MsgStream;
+class IPageAccessControlSvc;
+
+namespace SG {
+
+  class DataProxy;
+
+
+  /**
+   * @brief Hold DataProxy instances associated with a store.
+   *
+   * We have two ways of looking up a proxy.
+   *
+   * First, the proxy is stored by CLID/key in m_storeMap.  This is a map
+   * indexed by CLID; the values are maps indexed by key.
+   *
+   * Second, m_keyMap stores proxies indexed by the hashed CLID/key.
+   *
+   * A proxy may be entered multiple times in the maps if there are
+   * symlinks or aliases.
+   *
+   * A proxy may be given to the store that has the hashed key set,
+   * but not the CLID/key.  This is referred to as a `dummy' proxy.
+   * This can happen when we read a link to an object that's not
+   * described in the event's DataHeader.  In this case, the proxy
+   * is entered only in the second map, m_keyMap.  If we later look
+   * for a proxy by CLID/key and don't find it, we also look in m_keyMap
+   * to see if a dummy proxy has been entered there.  If so, that point
+   * we fill in the CLID/key fields of the proxy and also enter
+   * it in m_storeMap.
+   */
+  class DataStore : virtual public IProxyRegistry
+  {
+
+  public:
+
+    typedef IStringPool::sgkey_t                sgkey_t;
+    typedef std::map<CLID, SG::ProxyMap>        StoreMap;
+    typedef StoreMap::iterator                  StoreIterator;
+    typedef StoreMap::const_iterator            ConstStoreIterator;
+
+    typedef std::pair<SG::ConstProxyIterator, SG::ConstProxyIterator> constProxyRange;
+
+    /**
+     * @brief Constructor.
+     * @param pool The string pool associated with this store.
+     */
+    DataStore (IProxyDictWithPool& pool);
+    virtual ~DataStore();
+
+    void setStoreID(StoreID::type id) { m_storeID = id;}
+    virtual StoreID::type storeID() const { return m_storeID; }
+ 
+    // If FORCE is true, then force deleting of all proxies,
+    // even if they would normally only be reset.
+    void clearStore(bool force = false, MsgStream* pmlog=0);
+
+    //////////////////////////////////////////////////////////////////
+    /// \name Implementation of IProxyRegistry.
+    //@{
+    virtual StatusCode addToStore(const CLID& id, DataProxy* proxy);
+    /// return proxy for a given type/key pair
+    /// if key is empty returns the default proxy (currently last registered)
+    virtual DataProxy* proxy(const TransientAddress* tAddr) const; 
+    //@}
+    virtual DataProxy* proxy(const CLID& id, 
+			     const std::string& key=SG::DEFAULTKEY) const;
+
+    /// get proxy with given key. Returns 0 to flag failure
+    /// the key must match exactly (no wild carding for the default key)
+    SG::DataProxy* proxy_exact (sgkey_t sgkey) const;
+
+    /// get proxy with given id. Returns 0 to flag failure
+    /// the key must match exactly (no wild carding for the default key)
+    virtual SG::DataProxy* proxy_exact(const CLID& id,
+                                       const std::string& key) const;
+
+    /// remove proxy from store, unless proxy is reset only.   
+    /// @param forceRemove remove the proxy no matter what
+    StatusCode removeProxy(DataProxy* proxy, bool forceRemove=false);
+
+    /// add symlink to store:
+    StatusCode addSymLink(const CLID& linkid, DataProxy* proxy);
+
+    /// add alias to store
+    StatusCode addAlias(const std::string& aliasKey, DataProxy* proxy);
+
+    /// Count number of object of a given type in store
+    int typeCount(const CLID& id) const;
+
+    /// Return an iterator over the StoreMap:
+    StatusCode tRange(ConstStoreIterator& f, ConstStoreIterator& e) const;
+
+    /// Return an iterator over proxy for a given CLID:
+    StatusCode pRange(const CLID& id, SG::ConstProxyIterator& f,
+		      SG::ConstProxyIterator& e) const;
+
+    /// Return a list of all valid proxies in the store:
+    StatusCode proxyList(std::list<DataProxy*>& pList) const;
+
+
+    /// set IPageAccessControlSvc ptr in T2PMap
+    void setPac(IPageAccessControlSvc* pac) { m_t2p.setPac(pac); }
+    /// request an access control report, i.e. a list of proxies that have not been accessed since monitored
+    std::vector<DataProxy*> pacReport() const { return m_t2p.pacReport();}
+
+    /// methods to query the T2PMap:
+    StatusCode t2pRegister(const void* const pTrans, DataProxy* const pPers);
+    void t2pRemove(const void* const pTrans);
+
+    /// locate the persistent (proxy) for a given T* (void*):
+    DataProxy* locatePersistent(const void* const pTransient) const;
+
+    // return list of keys associated with an object
+    void keys(const CLID& id, std::vector<std::string>& vkeys,
+	      bool includeAlias, bool onlyValid);
+
+  private:
+
+    /// The string pool associated with this store.
+    IProxyDictWithPool& m_pool;
+
+    StoreMap m_storeMap;
+
+    /// Map of hashed sgkey -> DataProxy.
+    typedef SG::unordered_map<sgkey_t, DataProxy*> KeyMap_t;
+    KeyMap_t m_keyMap;
+
+    StoreID::type m_storeID;
+
+    // Map to hold the relation between transient and persistent object:
+    // we have changed to DataProxy as it is faster while recording
+    // to check if it already exists
+    T2pMap  m_t2p;
+
+    void setSGAudSvc() const;
+    mutable ISGAudSvc * m_pSGAudSvc;
+    mutable bool m_noAudSvc;    
+    inline bool doAudit() const {
+      if (!m_noAudSvc) setSGAudSvc();
+      return (m_pSGAudSvc);
+    }
+
+    ISvcLocator* m_pSvcLoc; 
+    StatusCode setSvcLoc();
+
+
+    /**
+     * @brief Look for (and convert) a matching dummy proxy.
+     * @param id The CLID for which to search.
+     * @param key The key for which to search.
+     *
+     * In some cases, we may enter into the store a `dummy' proxy,
+     * which is identified only by the hashed CLID/key pair.
+     * (This can happen when we have a link to an object that's not
+     * listed in the DataHeader; in this case, we know the only hashed key
+     * and not the CLID or key.)
+     *
+     * This function is called after we fail to find a proxy by CLID/key.
+     * It additionally checks to see if there exists a dummy proxy with
+     * a hash matching this CLID/key.  If so, the CLID/key are filled
+     * in in the proxy, and the proxy is entered in m_storeMap.
+     *
+     * Returns either the matching proxy or 0.
+     */
+    DataProxy* findDummy (CLID id, const std::string& key);
+  };
+  //////////////////////////////////////////////////////////////////
+  inline void
+  DataStore::t2pRemove(const void* const pTrans)
+  {
+    m_t2p.t2pRemove(pTrans);
+  }
+  //////////////////////////////////////////////////////////////////
+} //end namespace SG
+
+
+#endif  // STOREGATE_DATASTORE
+
diff --git a/Control/SGTools/SGTools/IProxyDictWithPool.h b/Control/SGTools/SGTools/IProxyDictWithPool.h
new file mode 100755
index 0000000000000000000000000000000000000000..b0e8807739d944eaf149c74da438050cd0eff478
--- /dev/null
+++ b/Control/SGTools/SGTools/IProxyDictWithPool.h
@@ -0,0 +1,58 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IProxyDictWithPool.h,v 1.2 2008-04-18 03:18:24 ssnyder Exp $
+/**
+ * @file SGTools/IProxyDictWithPool.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Mar, 2007
+ * @brief Combine IProxyDict and IStringPool.
+ *
+ * Make a class that combines @c IProxyDict and @c IStringPool,
+ * so we can use both through a single pointer without having
+ * to dynamic_cast between them.
+ */
+
+
+#ifndef SGTOOLS_IPROXYDICTWITHPOOL_H
+#define SGTOOLS_IPROXYDICTWITHPOOL_H
+
+#include "AthenaKernel/IProxyDict.h"
+#include "SGTools/IStringPool.h"
+
+
+/// Interface definition.
+static const InterfaceID IID_IProxyDictWithPool ("IProxyDictWithPool", 1, 0);
+
+
+/**
+ * @brief Combine IProxyDict and IStringPool.
+ */
+class IProxyDictWithPool
+  : public IProxyDict,
+    public IStringPool
+{
+public:
+  /// Gaudi interface definition.
+  static const InterfaceID& interfaceID() { return IID_IProxyDictWithPool; }
+
+
+  /**
+   * @brief Test to see if the target of an ElementLink has moved.
+   * @param sgkey_in Original hashed key of the EL.
+   * @param index_in Original index of the EL.
+   * @param sgkey_out[out] New hashed key for the EL.
+   * @param index_out[out] New index for the EL.
+   * @return True if there is a remapping; false otherwise.
+   *
+   * The default implementation here always returns false.
+   */
+  virtual bool tryELRemap (sgkey_t sgkey_in, size_t index_in,
+                           sgkey_t& sgkey_out, size_t& index_out);
+};
+
+
+#endif // not SGTOOLS_IPROXYDICTWITHPOOL_H
diff --git a/Control/SGTools/SGTools/IRegisterTransient.h b/Control/SGTools/SGTools/IRegisterTransient.h
new file mode 100644
index 0000000000000000000000000000000000000000..a503640e5e589a8c8570e7399cc808b1b6e5b4ae
--- /dev/null
+++ b/Control/SGTools/SGTools/IRegisterTransient.h
@@ -0,0 +1,47 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IRegisterTransient.h,v 1.2 2008-04-08 16:05:32 ssnyder Exp $
+
+/**
+ * @file  SGTools/IRegisterTransient.h
+ * @author scott snyder
+ * @date Mar, 2008
+ * @brief Interface for registering a transient object in t2p map.
+ */
+
+
+#ifndef SGTOOLS_IREGISTERTRANSIENT
+#define SGTOOLS_IREGISTERTRANSIENT
+
+
+namespace SG {
+
+
+/**
+ * @brief Interface for registering a transient object in t2p map.
+ *
+ * (See @c T2pMap.)
+ */
+class IRegisterTransient
+{
+public:
+  /// Destructor.
+  virtual ~IRegisterTransient() {}
+
+
+  /**
+   * @brief Register a transient object in a t2p map.
+   * @param trans The object to register.
+   */
+  virtual void registerTransient (void* trans) = 0;
+};
+
+
+} // namespace SG
+
+
+#endif // not SGTOOLS_IREGISTERTRANSIENT
diff --git a/Control/SGTools/SGTools/IStringPool.h b/Control/SGTools/SGTools/IStringPool.h
new file mode 100755
index 0000000000000000000000000000000000000000..cda84646227d91f0b09ed3423f43da23ddf0ebf6
--- /dev/null
+++ b/Control/SGTools/SGTools/IStringPool.h
@@ -0,0 +1,97 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IStringPool.h,v 1.3 2008-09-03 17:19:10 ssnyder Exp $
+/**
+ * @file SGTools/IStringPool.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Mar, 2007
+ * @brief Abstract interface for looking up strings/CLIDs in a pool.
+ */
+
+
+#ifndef SGTOOLS_ISTRINGPOOL_H
+#define SGTOOLS_ISTRINGPOOL_H
+
+
+#include "AthenaKernel/sgkey_t.h"
+#include "GaudiKernel/ClassID.h"
+#include "GaudiKernel/IInterface.h"
+#include <string>
+
+
+/// Interface definition.
+static const InterfaceID IID_IStringPool ("IStringPool", 1, 0);
+
+
+/**
+ * @brief Abstract interface for looking up strings/CLIDs in a pool.
+ */
+class IStringPool
+{
+public:
+  /// Gaudi interface definition.
+  static const InterfaceID& interfaceID() { return IID_IStringPool; }
+
+  /// Destructor.
+  virtual ~IStringPool() {}
+
+  /// Type of the keys.
+  typedef SG::sgkey_t sgkey_t;
+
+  /**
+   * @brief Find the key for a string/CLID pair.
+   * @param str The string to look up.
+   * @param clid The CLID associated with the string.
+   * @return A key identifying the string.
+   *         A given string will always return the same key.
+   *         Will abort in case of a hash collision!
+   */
+  virtual
+  sgkey_t stringToKey (const std::string& str, CLID clid) = 0;
+
+  /**
+   * @brief Find the string corresponding to a given key.
+   * @param key The key to look up.
+   * @return Pointer to the string found, or null.
+   *         We can find keys as long as the corresponding string
+   *         was given to either @c stringToKey() or @c registerKey().
+   */
+  virtual
+  const std::string* keyToString (sgkey_t key) const = 0;
+
+  /**
+   * @brief Find the string and CLID corresponding to a given key.
+   * @param key The key to look up.
+   * @param clid[out] The found CLID.
+   * @return Pointer to the string found, or null.
+   *         We can find keys as long as the corresponding string
+   *         was given to either @c stringToKey() or @c registerKey().
+   */
+  virtual
+  const std::string* keyToString (sgkey_t key,
+                                  CLID& clid) const = 0;
+
+  /**
+   * @brief Remember an additional mapping from key to string/CLID.
+   * @param key The key to enter.
+   * @param str The string to enter.
+   * @param clid The CLID associated with the string.
+   * @return True if successful; false if the @c key already
+   *         corresponds to a different string.
+   *
+   * This registers an additional mapping from a key to a string;
+   * it can be found later through @c lookup() on the string.
+   * Logs an error if @c key already corresponds to a different string.
+   */
+  virtual
+  void registerKey (sgkey_t key,
+                    const std::string& str,
+                    CLID clid) = 0;
+};
+
+
+#endif // not SGTOOLS_ISTRINGPOOL_H
diff --git a/Control/SGTools/SGTools/ProxyMap.h b/Control/SGTools/SGTools/ProxyMap.h
new file mode 100755
index 0000000000000000000000000000000000000000..088084653f393e08f1bc6365d1cbaeb8959c2338
--- /dev/null
+++ b/Control/SGTools/SGTools/ProxyMap.h
@@ -0,0 +1,31 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/***************************************************************************
+ the DataStore proxy map
+ ----------------------------
+ ATLAS Collaboration
+ ***************************************************************************/
+
+// $Id: ProxyMap.h,v 1.2 2003-04-16 01:49:26 calaf Exp $
+
+#ifndef SGTOOLS_PROXYMAP_H
+#define SGTOOLS_PROXYMAP_H
+
+#ifndef _CPP_MAP
+ #include <map>
+#endif
+#ifndef _CPP_STRING
+ #include <string>
+#endif
+
+namespace SG {
+  class DataProxy;
+
+  typedef std::map<std::string, DataProxy*>   ProxyMap;
+  typedef ProxyMap::iterator                  ProxyIterator;
+  typedef ProxyMap::const_iterator            ConstProxyIterator;
+}
+
+#endif // TOOLS_PROXYMAP_H
diff --git a/Control/SGTools/SGTools/SGFolderItem.h b/Control/SGTools/SGTools/SGFolderItem.h
new file mode 100755
index 0000000000000000000000000000000000000000..5847907fad54b341fc73a6c8632aad69a60ba302
--- /dev/null
+++ b/Control/SGTools/SGTools/SGFolderItem.h
@@ -0,0 +1,37 @@
+/* -*- C++ -*- */
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/** @file SGFolderItem.h
+ *  defines a class representing a folder item (data object clid/key)
+ */
+#ifndef SGTOOLS_FOLDERITEM_H
+#define SGTOOLS_FOLDERITEM_H
+#include <string>
+#include "GaudiKernel/ClassID.h"
+namespace SG {
+  /** @class SG::FolderItem
+   * @brief  a Folder item (data object) is identified by the clid/key pair
+   *
+   * @author pcalafiura@lbl.gov - ATLAS Collaboration
+   * $Id: SGFolderItem.h,v 1.2 2008-03-26 22:36:54 calaf Exp $
+   **/
+  class FolderItem {
+  public:
+    FolderItem(CLID id=CLID_NULL, const std::string& key="") : m_id(id), m_key(key) {}
+    CLID id() const { return m_id; }
+    const std::string& key() const { return m_key; }
+    bool operator < (const FolderItem& rhs) const {
+      return ( id() < rhs.id() || 
+	       ( (id() == rhs.id()) && key() < rhs.key()) );
+    }
+    bool isFolder() const;
+  private:
+    CLID m_id;
+    std::string m_key;
+  };
+} //ns SG
+
+#endif
diff --git a/Control/SGTools/SGTools/SGIFolder.h b/Control/SGTools/SGTools/SGIFolder.h
new file mode 100755
index 0000000000000000000000000000000000000000..e8b09a9a612362f88e06740f5f2f456bf1b42bf1
--- /dev/null
+++ b/Control/SGTools/SGTools/SGIFolder.h
@@ -0,0 +1,55 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef SGTOOLS_IFOLDER_H
+#define SGTOOLS_IFOLDER_H
+
+#include <set>
+#include <string>
+
+#ifndef GAUDIKERNEL_IALGTOOL_H
+ #include "GaudiKernel/IAlgTool.h"
+#endif
+
+#include "SGTools/SGFolderItem.h"
+
+namespace SG {  
+  /** @class SG::IFolder
+   * @brief a run-time configurable list of data objects
+   *
+   * @author pcalafiura@lbl.gov - ATLAS Collaboration
+   * $Id: SGIFolder.h,v 1.3 2008-04-24 00:55:21 calaf Exp $
+   **/
+  class IFolder : public virtual IAlgTool
+  {
+  public:
+    /// the list we manage
+    typedef std::set<FolderItem> ItemList; //FIXME would be nice to move to SG::Folder
+
+    /// \name access the ItemList
+    //@{
+    typedef ItemList::const_iterator const_iterator;
+    virtual const_iterator begin() const = 0;
+    virtual const_iterator end() const = 0;
+    //@}
+    ///add a data object identifier to the list
+    virtual StatusCode add(const std::string& typeName, const std::string& skey) = 0;
+    ///add a data object identifier to the list
+    virtual StatusCode add(const CLID& clid, const std::string& skey) = 0;
+
+    ///clear the folder contents
+    virtual void clear() = 0;
+
+    ///update list of items
+    virtual void updateItemList(bool checkValidCLID) = 0;
+    
+
+    static const InterfaceID& interfaceID() {
+      static const InterfaceID _IID( "SG::IFolder", 1, 0 );
+      return _IID;
+    }
+  };
+} //ns SG
+
+#endif
diff --git a/Control/SGTools/SGTools/SGToolsDict.h b/Control/SGTools/SGTools/SGToolsDict.h
new file mode 100755
index 0000000000000000000000000000000000000000..95e497b2fa15347dc7df858f720dc641b10f4798
--- /dev/null
+++ b/Control/SGTools/SGTools/SGToolsDict.h
@@ -0,0 +1,26 @@
+///////////////////////// -*- C++ -*- /////////////////////////////
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef SGTOOLS_SGTOOLSDICT_H
+#define SGTOOLS_SGTOOLSDICT_H
+
+#include <vector>
+#include "SGTools/IProxyDictWithPool.h"
+#include "SGTools/IStringPool.h"
+#include "SGTools/DataBucket.h"
+#include "SGTools/DataProxy.h"
+#include "SGTools/BaseInfo.h"
+
+// Need to instantiate iterators
+namespace SGToolsDict
+{
+  struct _tmp {
+    std::vector<      SG::DataProxy*> m_sg_data_proxies;
+    std::vector<const SG::DataProxy*> m_const_sg_data_proxies;
+  };
+}
+
+#endif // not SGTOOLS_SGTOOLSDICT_H
diff --git a/Control/SGTools/SGTools/SGVersionedKey.h b/Control/SGTools/SGTools/SGVersionedKey.h
new file mode 100644
index 0000000000000000000000000000000000000000..f79c2f6d0e7d2cc9af1768df19e510048ca0c3bf
--- /dev/null
+++ b/Control/SGTools/SGTools/SGVersionedKey.h
@@ -0,0 +1,104 @@
+/* -*- C++ -*- */
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/** @file SGVersionedKey.h
+ *  defines  a StoreGateSvc key with a version number 
+ */
+#ifndef SGTOOLS_VERSIONEDKEY_H
+#define SGTOOLS_VERSIONEDKEY_H 1
+#include <iostream>
+#include <string>
+class StoreGateSvc; //our friend
+class SGImplSvc; //our friend
+namespace SG {
+  /** @class SG::VersionedKey
+   * @brief  a StoreGateSvc key with a version number.
+   * Notice that StoreGate does not order multiple instances of an object with
+   * a given key by version number. A generic retrieve will always return
+   * the first version recorded. For example, if object ("MyKey",1) is recorded 
+   * _before__ ("MyKey", 2) a sg.retrieve(pObj,"MyKey") will return ("MyKey",1).
+   * StoreGateSvc provides retrieveAllVersions and retrieveHighestVersion,
+   * which offer a better-defined behaviour.
+   *
+   * @author pcalafiura@lbl.gov - ATLAS Collaboration
+   * $Id: SGVersionedKey.h,v 1.4 2008-07-10 15:51:04 dquarrie Exp $
+   **/
+  class VersionedKey {
+    friend class ::StoreGateSvc; //call copyVK
+    friend class ::SGImplSvc; //call copyVK
+  public:
+    ///quickly determine whether a string has the right format to be a VK
+    static bool isVersionedKey(const char *);
+    ///quickly determine whether a string has the right format to be a VK
+    static bool isVersionedKey(const std::string&);
+
+    /// version must be [0,99], 0 is the default version
+    VersionedKey(const char* key, unsigned char version);
+    /// version must be [0,99], 0 is the default version
+    VersionedKey(const std::string& key, unsigned char version);
+
+    /// make a VersionedKey from vkey string. If vkey has the
+    /// VersionedKey format (;NN;key), it is simply copied, otherwise
+    /// it is taken to be the real key, and version=0 is assigned
+    explicit VersionedKey(const char* vkey);
+    /// make a VersionedKey from vkey string. If vkey has the
+    /// VersionedKey format (;NN;key), it is simply copied, otherwise
+    /// it is taken to be the real key, and version=0 is assigned
+    explicit VersionedKey(const std::string& vkey);
+    
+    /// copy constructor transfers ownership a la auto_ptr (hence rhs
+    /// is not really const).
+    VersionedKey(const VersionedKey& rhs);
+
+    /// default constructor (invalid state, do not use)
+    VersionedKey(): m_versionKey(0) {}
+
+    ~VersionedKey();
+
+    /// sets key to point to encoded key, and version to encoded version (0 is taken to mean default version). 
+    void decode(char*& key, unsigned char& version) const;
+    /// convert underlying encoded m_versionKey C string
+    operator std::string() const { return std::string(m_versionKey); }
+    /// @returns version number
+    unsigned char version() const;
+    /// @returns base key
+    const char* key() const;
+    /// @returns access underlying encoded m_versionKey C string
+    const char* rawVersionKey() const {
+      return m_versionKey;
+    }
+    /// compare base keys
+    bool sameKey(const VersionedKey& vkey) const;
+    /// compare base keys
+    bool sameKey(const std::string& baseKey) const;
+    /// compare base keys
+    bool sameKey(const char* baseKey) const;
+
+  private:
+    void encode(const char* key, unsigned char version);
+    void copyVK(const char* versionedKey);
+    static char separator() {return ';';}
+    static const char* formatString() {return ";%02u;%s";}
+    ///the encoded version/key. Mutable so that ownership can be transferred
+    ///in the copy constructor
+    mutable char* m_versionKey; 
+
+    VersionedKey& operator= (const VersionedKey&);
+  };
+} // ns SG
+
+/// sort according to highest key version
+bool operator < (const SG::VersionedKey& lhs, const SG::VersionedKey& rhs);
+
+namespace SG {
+  inline
+    std::ostream& operator <<(std::ostream& ost, const SG::VersionedKey& k) {
+    return ost << k.rawVersionKey();
+    //  return ost.write(k.rawVersionKey(), strlen(k.rawVersionKey()));
+  }
+}
+
+#endif
diff --git a/Control/SGTools/SGTools/StlMapClids.h b/Control/SGTools/SGTools/StlMapClids.h
new file mode 100644
index 0000000000000000000000000000000000000000..30fdadbf7318990238e93a732d9bc6b121ea371b
--- /dev/null
+++ b/Control/SGTools/SGTools/StlMapClids.h
@@ -0,0 +1,39 @@
+///////////////////////// -*- C++ -*- /////////////////////////////
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// StlMapClids.h 
+// Header file for CLIDs for various std::map<T,U>
+// Author: S.Binet<binet@cern.ch>
+/////////////////////////////////////////////////////////////////// 
+#ifndef SGTOOLS_STLMAPCLIDS_H 
+#define SGTOOLS_STLMAPCLIDS_H 
+
+// STL includes
+#include <map>
+#include <string>
+#include <vector>
+
+// Gaudi includes
+
+// SGTools includes
+#include "SGTools/CLASS_DEF.h"
+
+CLASS_DEF2( std::map<int,int> ,    103402598 , 1 )
+CLASS_DEF2( std::map<int,float> ,  256222847 , 1 )
+CLASS_DEF2( std::map<int,double> , 235483215 , 1 )
+
+CLASS_DEF2( std::map<std::string,int> ,          170542827 , 1 )
+CLASS_DEF2( std::map<std::string,unsigned int> , 113556225 , 1 )
+CLASS_DEF2( std::map<std::string,float> ,        193758082 , 1 )
+CLASS_DEF2( std::map<std::string,double> ,       252602412 , 1 )
+CLASS_DEF2( std::map<std::string,std::string> , 143489258 , 1 )
+
+CLASS_DEF2( std::map<std::string,std::vector<int> > ,          181049313 , 1 )
+CLASS_DEF2( std::map<std::string,std::vector<unsigned int> > , 199376827 , 1 )
+CLASS_DEF2( std::map<std::string,std::vector<float> > ,        259112316 , 1 )
+CLASS_DEF2( std::map<std::string,std::vector<double> > ,        78422682 , 1 )
+
+#endif // !SGTOOLS_STLMAPCLIDS_H
diff --git a/Control/SGTools/SGTools/StlVectorClids.h b/Control/SGTools/SGTools/StlVectorClids.h
new file mode 100644
index 0000000000000000000000000000000000000000..c67a3107080f6bcb12ccc8bd0247e7dc876fb9ff
--- /dev/null
+++ b/Control/SGTools/SGTools/StlVectorClids.h
@@ -0,0 +1,52 @@
+///////////////////////// -*- C++ -*- /////////////////////////////
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// StlVectorClids.h 
+// Header file for CLIDs for various std::vector<T>
+// Author: S.Binet<binet@cern.ch>
+/////////////////////////////////////////////////////////////////// 
+#ifndef SGTOOLS_STLVECTORCLIDS_H 
+#define SGTOOLS_STLVECTORCLIDS_H 
+
+// STL includes
+#include <vector>
+#include <string>
+#include <stdint.h>
+
+// Gaudi includes
+
+// SGTools includes
+#include "SGTools/CLASS_DEF.h"
+
+CLASS_DEF( std::vector<bool> ,            45822813 , 1 )
+CLASS_DEF( std::vector<short> ,           35706084 , 1 )
+CLASS_DEF( std::vector<int> ,             22592129 , 1 )
+CLASS_DEF( std::vector<long> ,             6675975 , 1 )
+CLASS_DEF( std::vector<float> ,          202242136 , 1 )
+CLASS_DEF( std::vector<double> ,         219400222 , 1 )
+CLASS_DEF( std::vector<std::string> ,     25884436 , 1 )
+
+CLASS_DEF( std::vector<unsigned short> , 238793770 , 1 )
+CLASS_DEF( std::vector<unsigned int> ,   177480351 , 1 )
+CLASS_DEF( std::vector<unsigned long> ,      18868981 , 1 )
+CLASS_DEF( std::vector<unsigned long long> , 35119468 , 1 )
+
+CLASS_DEF( std::vector<std::vector<char> > ,               70698075 , 1 )
+CLASS_DEF( std::vector<std::vector<short> > ,              24204906 , 1 )
+CLASS_DEF( std::vector<std::vector<int> > ,                23262399 , 1 )
+CLASS_DEF( std::vector<std::vector<uint8_t> > ,           126048273 , 1 )
+CLASS_DEF( std::vector<std::vector<unsigned short> > ,    247252788 , 1 )
+CLASS_DEF( std::vector<std::vector<unsigned int> > ,      213985193 , 1 )
+CLASS_DEF( std::vector<std::vector<unsigned long> > ,     205717523 , 1 )
+CLASS_DEF( std::vector<std::vector<unsigned long long> > , 76977490 , 1 )
+CLASS_DEF( std::vector<std::vector<float> > ,        258753314 , 1 )
+CLASS_DEF( std::vector<std::vector<double> > ,       154043868 , 1 )
+CLASS_DEF( std::vector<std::vector<std::string> > ,  101141770 , 1 )
+
+CLASS_DEF( std::vector<std::vector<std::vector<int> > > ,   85220325 , 1 )
+CLASS_DEF( std::vector<std::vector<std::vector<float> > > , 82469196 , 1 )
+
+#endif // !SGTOOLS_STLVECTORCLIDS_H
diff --git a/Control/SGTools/SGTools/StorableConversions.h b/Control/SGTools/SGTools/StorableConversions.h
new file mode 100755
index 0000000000000000000000000000000000000000..f0838677e0d119b2e9c83458173a571217f952b4
--- /dev/null
+++ b/Control/SGTools/SGTools/StorableConversions.h
@@ -0,0 +1,262 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef SGTOOLS_STORABLECONVERSIONS_H
+# define SGTOOLS_STORABLECONVERSIONS_H
+/** @file StorableConversions.h
+ *  @brief convert to and from a SG storable
+ * $Id: StorableConversions.h,v 1.13 2008-05-22 22:54:12 calaf Exp $
+ * @author ATLAS Collaboration
+ **/
+
+//<<<<<< INCLUDES                                                       >>>>>>
+#include "SGTools/DataBucket.h"
+#include "SGTools/ClassID_traits.h"
+#include "SGTools/DataBucketTraitFwd.h"
+#include "AthenaKernel/tools/type_tools.h"
+#include "GaudiKernel/DataObject.h"
+
+#ifndef NDEBUG
+#  include "AthenaKernel/getMessageSvc.h"
+#  include "GaudiKernel/MsgStream.h"
+#endif
+
+#include "boost/type_traits/is_same.hpp"
+#include "boost/mpl/identity.hpp"
+#include "boost/mpl/eval_if.hpp"
+#include <memory>
+
+//
+//<<<<<< FORWARD DECLARATIONS                                           >>>>>>
+
+//<<<<<< FUNCTION DECLARATIONS                                          >>>>>>
+namespace SG {
+
+  // put a dobj pointer in a bucket as appropriate
+  template <typename T> 
+  DataObject* asStorable(T* pObject);
+
+  // get a dobj pointer from a bucket as appropriate
+  template <typename T> 
+  bool  fromStorable(DataObject* pDObj, T*& pTrans, bool quiet=false,
+                     IRegisterTransient* irt = 0,
+                     bool isConst = true);
+
+  template <typename T>
+  T* Storable_cast(DataObject* pDObj, bool quiet=true,
+                   IRegisterTransient* irt = 0,
+                   bool isConst = true) {
+    T* result;
+    return  fromStorable(pDObj, result, quiet, irt, isConst) ? result : 0;
+  }
+  template <typename T>
+  const T* Storable_cast(const DataObject* pDObj, bool quiet=true,
+                         IRegisterTransient* irt = 0,
+                         bool isConst = true) {
+    return Storable_cast<T>(const_cast<DataObject*>(pDObj), quiet, irt, isConst);
+  }
+
+  class bad_Storable_cast : public std::bad_cast {};
+  template<typename T>
+  T& Storable_cast(const DataObject& dObj, bool quiet=true,
+                   IRegisterTransient* irt = 0,
+                   bool isConst = true)
+  {
+    T* result(0);
+    if (!fromStorable(const_cast<DataObject*>(&dObj),
+                      result, quiet, irt, isConst)) throw bad_Storable_cast();
+    return *(const_cast<T*>(result));
+  }
+
+
+  /**
+   * @brief Try to get the pointer back from a @a DataObject,
+   *        converted to be of type @a clid.
+   * @param pDObj The @a DataObject.
+   * @param clid The ID of the class to which to convert.
+   * @param irt To be called if we make a new instance.
+   * @param isConst True if the object being converted is regarded as const.
+   *
+   * Only works if the @a DataObject is a @a DataBucket.
+   * Returns 0 on failure,
+   */
+  void* fromStorable(DataObject* pDObj, CLID clid,
+                     IRegisterTransient* irt = 0,
+                     bool isConst = true);
+
+
+  /**
+   * @brief Try to get the pointer back from a @a DataObject,
+   *        converted to be of type @a clid.
+   * @param pDObj The @a DataObject.
+   * @param clid The ID of the class to which to convert.
+   * @param irt To be called if we make a new instance.
+   * @param isConst True if the object being converted is regarded as const.
+   *
+   * Only works if the @a DataObject is a @a DataBucket.
+   * Returns 0 on failure,
+   */
+  void* Storable_cast(DataObject* pDObj, CLID clid,
+                      IRegisterTransient* irt = 0,
+                      bool isConst = true);
+
+  /**
+   * @brief Try to get the pointer back from a @a DataObject,
+   *        converted to be of type @a clid.
+   * @param pDObj The @a DataObject.
+   * @param clid The ID of the class to which to convert.
+   * @param irt To be called if we make a new instance.
+   * @param isConst True if the object being converted is regarded as const.
+   *
+   * Only works if the @a DataObject is a @a DataBucket.
+   * Returns 0 on failure,
+   */
+  const void* Storable_cast(const DataObject* pDObj, CLID clid,
+                            IRegisterTransient* irt = 0,
+                            bool isConst = true);
+}
+
+//////////////////////////////////////////////////////////////////
+// implementation details
+
+
+namespace SG {
+
+
+  /**
+   * @brief Metafunction to find the proper @c DataBucket class for @c T.
+   *
+   * Here's what we're trying to do.
+   *
+   * The default @c DataBucket class for @c T is @c SG::DataBucket\<T>.
+   *
+   * However, if @c T is a @c DataVector or @c DataList, then we want
+   * to use instead @c SG::DVLDataBucket\<T>.
+   *
+   * Further, if @c T derives from @c DataVector or @c DataList (as declared
+   * by @c SG_BASE), then we also want to use @c SG::DVLDataBucket\<T>.
+   *
+   * Further, we don't want this code to depend on @c DataVector
+   * or @c SG::DVLDataBucket.  That behavior is enabled only
+   * by including the appropriate @c DataVector/@c DataList headers.
+   *
+   * So, we handle this with the following metafunction.
+   * (By saying that this is a `metafunction', it means that the result
+   * is given by the nested type @c type.)
+   * The @c T argument is the type we're testing, and @c U is the top-level
+   * type that was given to the original invocation of @c DataBucketTrait.
+   * If @c T has no bases (according to @c SG::Bases), we return
+   * @c SG::DataBucket\<U>.  Otherwise, we apply ourselves recursively
+   * to the first base class.
+   *
+   * Other packages can then specialize this to change the behavior.
+   *
+   * We don't really try to handle multiple bases.  In principle,
+   * we could loop over them.  But it seems that that's not really needed,
+   * so i don't want to pull in the extra overhead unnecessarily.
+   *
+   * This class also defines a real static function init().
+   * This is called from @c fromStorable.
+   * It can be used to force instantiation of reflection information.
+   */
+  template <class T, class U /* = T*/>
+  struct DataBucketTrait
+  {
+    // The first base of @c T (or @c SG::NoBase).
+    typedef typename SG::BaseType<typename SG::Bases<T>::Base1>::type base1;
+
+    // Test to see if it's valid.
+    typedef typename boost::is_same<base1, SG::NoBase>::type has_base;
+
+    // This is what we'll return in the default (no base) case.
+    typedef boost::mpl::identity<SG::DataBucket<U> > deflt;
+
+    // This is what we use to recursively check the base
+    typedef DataBucketTrait<base1, U> recurse;
+
+    // Calculate the output.
+    // (Note that it's important to use @c eval_if here; otherwise,
+    // applying this to @c SG::NoBase won't work.)
+    typedef typename boost::mpl::eval_if<has_base, deflt, recurse>::type type;
+
+    /// Initialization hook.  A no-op by default.
+    static void init() {}
+  };
+
+
+  // put a dobj pointer in a bucket as appropriate
+  template <typename T>
+  DataObject* asStorable(T* pObject) {
+    typedef typename DataBucketTrait<T>::type bucket_t;
+    return new bucket_t (pObject);
+  }  
+
+#if __cplusplus > 201100
+  template <typename T>
+  DataObject* asStorable(std::unique_ptr<T> pObject) {
+    typedef typename DataBucketTrait<T>::type bucket_t;
+    return new bucket_t (std::move(pObject));
+  }  
+#endif
+
+  // get a dobj pointer from a bucket as appropriate
+  //the DataObject must be a DataBucket<DATA>*.
+
+  template <typename T>
+  bool  fromStorable(DataObject* pDObj, T*& pTrans, 
+                     bool
+#ifndef NDEBUG
+                     quiet
+#endif
+                     , IRegisterTransient* irt,
+                     bool isConst /*= true*/)
+  {
+    typedef typename DataBucketTrait<T>::type bucket_t;
+    DataBucketTrait<T>::init();
+
+    //check inputs
+    if (0 == pDObj) {
+      pTrans=0;
+#ifndef NDEBUG
+      MsgStream gLog(Athena::getMessageSvc(), "SG::fromStorable");
+      gLog << MSG::WARNING << "null input pointer " << endreq;
+#endif
+      return false;
+    }
+
+    // get T* from DataBucket:
+    SG::DataBucket<T>* bucketPtr = dynamic_cast<bucket_t*>(pDObj);
+    bool success(0 != bucketPtr);
+    if (success)
+      pTrans = *bucketPtr;
+    else {
+      // Try to use BaseInfo information to convert pointers.
+      DataBucketBase* b = dynamic_cast<DataBucketBase*>(pDObj);
+      if (b) {
+        pTrans = b->template cast<T> (irt, isConst);
+        if (pTrans)
+          success = true;
+      }
+    }
+
+#ifndef NDEBUG
+    if (!quiet && !success) {
+      MsgStream gLog(Athena::getMessageSvc(), "SG::fromStorable");
+      gLog << MSG::WARNING 
+		<< "can't convert stored DataObject " << pDObj 
+		<< " to type ("
+		<< ClassID_traits<T>::typeName() 
+		<< ")\n Unless you are following a symlink,"
+	        << " it probably means you have a duplicate "
+		<< "CLID = "  << pDObj->clID() 
+		<< endreq;
+    }
+#endif
+    return success;
+  }
+}
+
+#endif // SGTOOLS_STORABLECONVERSIONS_H
diff --git a/Control/SGTools/SGTools/StringPool.h b/Control/SGTools/SGTools/StringPool.h
new file mode 100755
index 0000000000000000000000000000000000000000..3897312a354a2faf545d5e497888ac28c5ddede8
--- /dev/null
+++ b/Control/SGTools/SGTools/StringPool.h
@@ -0,0 +1,114 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: StringPool.h,v 1.4 2008-09-03 17:19:10 ssnyder Exp $
+/**
+ * @file  SGTools/StringPool.h
+ * @author scott snyder
+ * @date Mar 2007
+ * @brief Maintain a mapping of strings to 64-bit ints.
+ *
+ * We map from strings to integer keys using a hash function.
+ * We keep a table of hashed strings so that we can later return the string
+ * given the key.
+ * We allow registering additional key->string mappings as well, as long
+ * as there aren't collisions.
+ * We also keep an auxiliary int that gets hashed along with the string.
+ */
+
+#ifndef SGTOOLS_STRINGPOOL_H
+#define SGTOOLS_STRINGPOOL_H
+
+#include <stdint.h>
+#include <string>
+
+namespace SG {
+
+class StringPoolImpl;
+
+class StringPool
+{
+public:
+  /// Type of the integer keys.
+  typedef uint32_t sgkey_t;
+
+  /// Type of auxiliary data.
+  typedef unsigned int sgaux_t;
+
+  /// Number of bits we'll use in the keys.
+  /// Leave a few spare bits in case we want to overload them for flags later.
+  static const int sgkey_t_nbits = 30;
+  static const sgkey_t sgkey_t_max =
+    (static_cast<sgkey_t>(1) << sgkey_t_nbits) - 1;
+
+  /// Constructor.
+  StringPool();
+
+  /// Destructor.
+  ~StringPool();
+
+  /**
+   * @brief Find the key for a string.
+   * @param str The string to look up.
+   * @param aux Auxiliary data to include along with the string.
+   * @return A key identifying the string.
+   *         A given string will always return the same key.
+   *         Will abort in case of a hash collision!
+   */
+  sgkey_t stringToKey (const std::string& str, sgaux_t aux = 0);
+
+  /**
+   * @brief Find the string corresponding to a given key.
+   * @param key The key to look up.
+   * @return Pointer to the string found, or null.
+   *         We can find keys as long as the corresponding string
+   *         was given to either @c stringToKey() or @c registerKey().
+   */
+  const std::string* keyToString (sgkey_t key) const;
+
+  /**
+   * @brief Find the string corresponding to a given key.
+   * @param key The key to look up.
+   * @param aux[out] Auxiliary data associated with the key.
+   * @return Pointer to the string found, or null.
+   *         We can find keys as long as the corresponding string
+   *         was given to either @c stringToKey() or @c registerKey().
+   */
+  const std::string* keyToString (sgkey_t key, sgaux_t& aux) const;
+
+  /**
+   * @brief Remember an additional mapping from key to string.
+   * @param key The key to enter.
+   * @param str The string to enter.
+   * @param aux Auxiliary data to include along with the string.
+   * @return True if successful; false if the @c key already
+   *         corresponds to a different string.
+   *
+   * This registers an additional mapping from a key to a string;
+   * it can be found later through @c lookup() on the string.
+   */
+  bool registerKey (sgkey_t key,
+                    const std::string& str,
+                    sgaux_t aux = 0);
+
+  /**
+   * @brief Debugging dump.  Write to cout.
+   */
+  void dump () const;
+
+private:
+  StringPoolImpl* m_impl;
+
+  // Don't allow copying.
+  StringPool (const StringPool&);
+  StringPool& operator= (const StringPool&);
+};
+
+
+} // namespace SG
+
+
+#endif // not SGTOOLS_STRINGPOOL_H
diff --git a/Control/SGTools/SGTools/T2pMap.h b/Control/SGTools/SGTools/T2pMap.h
new file mode 100755
index 0000000000000000000000000000000000000000..94e95ac9a51587fe197b57e5c68670be0fa0f827
--- /dev/null
+++ b/Control/SGTools/SGTools/T2pMap.h
@@ -0,0 +1,72 @@
+/* -*- C++ -*- */
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef SGTOOLS_T2PMAP_H
+#define SGTOOLS_T2PMAP_H
+
+#include "CxxUtils/unordered_map.h"
+#include "SGTools/ptrhash.h"
+#include <utility>
+#include <vector>
+#include "AthenaKernel/IPageAccessControlSvc.h"
+
+namespace SG { 
+
+class DataProxy;
+
+class T2pMap {
+
+ public:
+  
+  typedef SG::unordered_map<const void*, DataProxy*, ptrhash> t2p;
+
+  // constructor
+  T2pMap(IPageAccessControlSvc* pac=0) : m_pac(pac) { };
+
+  // Destructor
+  ~T2pMap() { };
+
+  // associate a void* (T*) with a proxy
+  bool t2pRegister(const void* const pTrans, DataProxy* const pPers) {
+    bool success(m_t2p.insert (std::make_pair (pTrans, pPers)) . second);
+    if (m_pac) m_pac->controlPage(pTrans);
+    return success;
+  }
+
+  // locate a proxy in t2p map
+  DataProxy* locatePersistent(const void* const pTransient) const {
+    t2p::const_iterator i = m_t2p.find(pTransient);
+
+    if (i == m_t2p.end())
+      return 0;
+    else
+      return i->second;
+  }
+
+  // clear the t2p map
+  void clear() {
+    m_t2p.clear();
+  }
+
+  // remove a void* from t2p
+  void t2pRemove(const void* const pTrans) {
+    m_t2p.erase(pTrans);
+  }
+
+  /// set IPageAccessControlSvc ptr in T2PMap
+  void setPac(IPageAccessControlSvc* pac) { m_pac=pac; }
+  /// request an access control report, i.e. a list of proxies that have not been accessed since under control;
+  std::vector<DataProxy*> pacReport() const;
+
+
+ private:
+  IPageAccessControlSvc* m_pac;
+  t2p m_t2p;
+
+};
+
+}
+#endif
diff --git a/Control/SGTools/SGTools/TransientAddress.h b/Control/SGTools/SGTools/TransientAddress.h
new file mode 100755
index 0000000000000000000000000000000000000000..81ecf52bf3326932533cc7d3cc7585956e20d214
--- /dev/null
+++ b/Control/SGTools/SGTools/TransientAddress.h
@@ -0,0 +1,280 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef SGTOOLS_TRANSIENTADDRESS_H
+#define SGTOOLS_TRANSIENTADDRESS_H
+
+///< includes:
+#include <string>
+#include <set>
+
+
+///< Gaudi includes:
+#include "SGTools/IStringPool.h"
+#include "GaudiKernel/ClassID.h"
+#include "AthenaKernel/StoreID.h"
+
+///< forward declarations:
+class IOpaqueAddress;
+class IAddressProvider;
+
+namespace SG {
+
+  class TransientAddress
+  {
+
+  public:
+
+    typedef std::set<CLID> TransientClidSet;
+    typedef std::set<std::string> TransientAliasSet;
+    typedef IStringPool::sgkey_t sgkey_t;
+
+    ///< Default Constructor
+    TransientAddress();
+
+    ///< Construct from clid and string key:
+    TransientAddress(const CLID& id, const std::string& key);
+
+    ///< Construct from clid, key and IOpaqueAddress
+    TransientAddress(const CLID& id, const std::string& key, 
+		     IOpaqueAddress* addr, bool clearAddress = true);
+
+    ///< Destructor
+    virtual ~TransientAddress();
+
+    /// Set the CLID / key.
+    /// This will only succeed if the clid/key are currently clear.
+    void setID (CLID id, const std::string& key);
+
+    ///< Reset
+    void reset();
+
+    ///< Retrieve IOpaqueAddress
+    virtual IOpaqueAddress* address() const; 
+
+    ///< set IOpaqueAddress
+    virtual void setAddress(IOpaqueAddress* pAddress);
+
+    ///< Retrieve primary clid
+    CLID clID() const;
+
+    ///< Retrieve string key:
+    const std::string& name() const;
+
+    ///< Get the primary (hashed) SG key.
+    sgkey_t sgkey() const;
+
+    ///< Set the primary (hashed) SG key.
+    void setSGKey (sgkey_t sgkey);
+
+    ///< check if it is a transient ID (primary or symLinked):
+    bool transientID (const CLID& id) const;
+
+    ///< set transient CLID's
+    void setTransientID(const CLID& id);
+
+    ///< get transient CLID's
+    const TransientClidSet& transientID() const;
+
+    ///< set alias'
+    void setAlias(const std::string& key);
+
+    ///< set alias'
+    void setAlias(const std::set<std::string>& keys);
+
+    /// remove alias from proxy
+    bool removeAlias(const std::string& key);
+
+    ///< get transient alias
+    const TransientAliasSet& alias() const;
+
+    ///< set the clearAddress flag: IOA will not be deleted in proxy
+    void clearAddress(const bool& flag);
+
+    ///< this sets the flag whether to consult the provider to update
+    /// this transient address if the IOA is not valid.
+    void consultProvider(const bool& flag);
+
+    ///< Check the validity of the Transient Address.
+    bool isValid();
+
+    ///< cache the pointer to the Address provider which can update
+    ///< this transient address
+    IAddressProvider* provider() const;
+    StoreID::type storeID() const;
+    void setProvider(IAddressProvider* provider, StoreID::type storeID);
+
+  private:
+
+    ///< clid of the concrete class (persistent clid)
+    CLID m_clid;
+
+    ///< string key of this object
+    std::string m_name;
+
+    ///< all transient clids. They come from symlinks
+    TransientClidSet m_transientID; 
+
+    ///< all alias names for a DataObject. They come from setAlias
+    TransientAliasSet m_transientAlias;
+
+    ///< IOpaqueAddress:
+    IOpaqueAddress* m_address;
+
+    ///< Controls if IOpaqueAddress should be deleted:
+    bool m_clearAddress;
+
+    ///< Control whether the Address Provider must be consulted
+    bool m_consultProvider;
+
+    ///< AddressProvider
+    IAddressProvider* m_pAddressProvider;
+
+    ///< Store type, needed by updateAddress
+    StoreID::type m_storeID;
+
+    ///< (hashed) SG key for primary clid / key.
+    sgkey_t m_sgkey;
+  };
+  /////////////////////////////////////////////////////////////////////
+  // inlined code:
+  /////////////////////////////////////////////////////////////////////
+
+  // Reset the TransientAddress
+  inline
+  void TransientAddress::reset()
+  {
+    if (m_clearAddress) setAddress(0);
+  }
+
+  /// Retrieve IOpaqueAddress
+  inline
+  IOpaqueAddress* TransientAddress::address() const 
+  { 
+    return m_address; 
+  }
+
+  /// Retrieve clid
+  inline
+  CLID TransientAddress::clID() const 
+  { 
+    return m_clid; 
+  }
+
+  /// Return StoreGate key
+  inline
+  const std::string& TransientAddress::name() const
+  {
+    return m_name;
+  }
+
+  /// Get the primary (hashed) SG key.
+  inline
+  TransientAddress::sgkey_t TransientAddress::sgkey() const
+  {
+    return m_sgkey;
+  }
+
+  /// Set the primary (hashed) SG key.
+  inline
+  void TransientAddress::setSGKey (sgkey_t sgkey)
+  {
+    m_sgkey = sgkey;
+  }
+
+  /// check if it is a transient ID:
+  inline
+  bool TransientAddress::transientID(const CLID& id) const
+  { 
+    return 0 != m_transientID.count(id);
+  }
+
+  /// set transient CLID's
+  inline
+  void TransientAddress::setTransientID(const CLID& id)
+  { 
+    m_transientID.insert(id);
+  }
+
+  /// get transient CLID's
+  inline
+  const TransientAddress::TransientClidSet& TransientAddress::transientID() const 
+  { 
+    return m_transientID; 
+  }
+
+  /// set transient Alias'
+  inline 
+  void TransientAddress::setAlias(const std::string& key)
+  {
+    m_transientAlias.insert(key);
+  } 
+
+  /// set transient Alias'
+  inline 
+  void TransientAddress::setAlias(const std::set<std::string>& keys)
+  {
+    m_transientAlias = keys;
+  } 
+
+  /// remove alias
+  inline bool TransientAddress::removeAlias(const std::string& key)
+  {
+    return (m_transientAlias.erase(key) == 1) ? true:false;
+  }
+
+  /// get transient Alias'
+  inline
+  const TransientAddress::TransientAliasSet& TransientAddress::alias() const
+  { 
+    return m_transientAlias;
+  }
+
+  /// set the clearAddress flag: IOA will not be deleted in proxy
+  inline
+  void TransientAddress::clearAddress(const bool& flag) 
+  {
+    m_clearAddress = flag;
+  }
+
+  inline
+  void TransientAddress::consultProvider(const bool& flag)
+  {
+    m_consultProvider = flag;
+  }
+
+  ///< cache the pointer to the Address provider which can update
+  ///< this transient address
+  inline
+  IAddressProvider* TransientAddress::provider() const
+  {
+    return m_pAddressProvider;
+  }
+  inline
+  StoreID::type TransientAddress::storeID() const
+  {
+    return m_storeID;
+  }
+
+  inline
+    void TransientAddress::setProvider(IAddressProvider* provider, 
+				       StoreID::type storeID)
+  {
+    m_pAddressProvider = provider;
+    m_consultProvider = true;
+    m_storeID=storeID;
+  }
+} //end namespace SG
+
+#endif // STOREGATE_TRANSIENTADDRESS
+
+
+
+
+
+
+
+
+
+
diff --git a/Control/SGTools/SGTools/crc64.h b/Control/SGTools/SGTools/crc64.h
new file mode 100755
index 0000000000000000000000000000000000000000..d9a017ca7db4d1030dcc27b87686bce43ea0e2a8
--- /dev/null
+++ b/Control/SGTools/SGTools/crc64.h
@@ -0,0 +1,56 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+/**
+ * @file  SGTools/crc64.h
+ * @author scott snyder, originally from David T. Jones
+ * @date Mar 2007
+ * @brief A CRC-64 implementation.
+ */
+
+#ifndef SGTOOLS_CRC64_H
+#define SGTOOLS_CRC64_H
+
+
+#include <string>
+#include <stdint.h>
+
+
+namespace SG {
+
+
+/**
+ * @brief Find the CRC-64 of a string.
+ * @param str The string to hash.
+ */
+uint64_t crc64 (const std::string& str);
+
+
+/**
+ * @brief Extend a previously-calculated CRC to include an int.
+ * @param crc The previously-calculated CRC.
+ * @param x The integer to add.
+ * @return The new CRC.
+ */
+uint64_t crc64addint (uint64_t crc, unsigned int x);
+
+
+/**
+ * @brief Format a CRC-64 as a string.
+ * @param crc The CRC to format.
+ */
+std::string crc64format (uint64_t crc);
+
+
+/**
+ * @brief Return a CRC-64 digest of a string.
+ * @param str The string to hash.
+ * @return The CRC-64 digest of the string.
+ *         This is the hash code, expressed as hex as a string.
+ */
+std::string crc64digest (const std::string& str);
+
+
+} // namespace SG
+
+
+
+#endif // not SGTOOLS_CRC64_H
diff --git a/Control/SGTools/SGTools/exceptions.h b/Control/SGTools/SGTools/exceptions.h
new file mode 100644
index 0000000000000000000000000000000000000000..2de48a5cab1753d3793d107addd977c2d71a3eb2
--- /dev/null
+++ b/Control/SGTools/SGTools/exceptions.h
@@ -0,0 +1,97 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file SGTools/exceptions.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Nov, 2013
+ * @brief Exceptions that can be thrown by SGTools.
+ */
+
+
+#ifndef SGTOOLS_EXCEPTIONS_H
+#define SGTOOLS_EXCEPTIONS_H
+
+
+#include "GaudiKernel/ClassID.h"
+#include <typeinfo>
+#include <stdexcept>
+#include <string>
+
+
+namespace SG {
+
+
+/**
+ * @brief Exception --- Bad cast of DataProxy with CLID 
+ *
+ * You tried to retrieve an object in StoreGate as an incompatible type.
+ */
+class ExcBadDataProxyCast
+  : public std::bad_cast
+{
+public:
+  /**
+   * @brief Constructor.
+   * @param id CLID of the DataProxy.
+   * @param tid Type to which we're trying to convert the object.
+   */
+  ExcBadDataProxyCast (CLID id, const std::type_info& tid);
+
+
+  // Needed for c++98 compatibility.
+  ~ExcBadDataProxyCast() throw() {}
+
+
+  /**
+   * @brief Return the message for this exception.
+   */
+  virtual const char* what() const throw();
+
+
+private:
+  /// The message for this exception.
+  std::string m_what;
+};
+
+
+/**
+ * @brief Throw an ExcBadDataProxyCast exception.
+ * @param id CLID of the DataProxy.
+ * @param tid Type to which we're trying to convert the object.
+ */
+void throwExcBadDataProxyCast (CLID id, const std::type_info& tid);
+
+
+/**
+ * @brief Exception --- Proxy collision for clid/key
+ *
+ * DataStore was attempting to fill in the CLID/key for a dummy proxy,
+ * but there was already another proxy present with that CLID/key.
+ *
+ * This should never happen.
+ */
+class ExcProxyCollision
+  : public std::runtime_error
+{
+public:
+  /**
+   * @brief Constructor.
+   * @param id CLID we're trying to set on the dummy proxy.
+   * @param key Key we're trying to set on the dummy proxy.
+   * @param primary_id CLID of the existing proxy.
+   * @param primary_key Key of the existing proxy.
+   */
+  ExcProxyCollision (CLID id, const std::string& key,
+                     CLID primary_id, const std::string& primary_key);
+};
+
+
+} // namespace SG
+
+
+#endif // not SGTOOLS_EXCEPTIONS_H
diff --git a/Control/SGTools/SGTools/hashtable.h b/Control/SGTools/SGTools/hashtable.h
new file mode 100755
index 0000000000000000000000000000000000000000..42d0e2989fc6026bd051e3f5d00ea6eb9f677466
--- /dev/null
+++ b/Control/SGTools/SGTools/hashtable.h
@@ -0,0 +1,17 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: hashtable.h,v 1.2 2008-09-17 01:17:05 binet Exp $
+
+#ifndef SGTOOLS_HASHTABLE_H
+#define SGTOOLS_HASHTABLE_H 1
+
+#ifndef CXXUTILS_HASHTABLE_H
+ #include "CxxUtils/hashtable.h"
+#endif
+
+#endif /* !SGTOOLS_HASHTABLE_H */
+
diff --git a/Control/SGTools/SGTools/ptrhash.h b/Control/SGTools/SGTools/ptrhash.h
new file mode 100644
index 0000000000000000000000000000000000000000..b807abbaf06e13aaad7fa9ad315005d16d6568fd
--- /dev/null
+++ b/Control/SGTools/SGTools/ptrhash.h
@@ -0,0 +1,50 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: ptrhash.h,v 1.1 2008-04-08 16:05:32 ssnyder Exp $
+/**
+ * @file SGTools/ptrhash.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Mon, 2008
+ * @brief Improved hash function for pointers.
+ */
+
+
+#ifndef SGTOOLS_PTRHASH_H
+#define SGTOOLS_PTRHASH_H
+
+
+namespace SG {
+
+
+/**
+ * @brief Improved hash function for pointers.
+ *
+ * The default hash function for pointers used by @c unordered_map and friends
+ * is just the result of casting the pointer to an int.
+ * The problem is that most pointers one deals with are going
+ * to be aligned; if the pointers are to objects obtained through malloc,
+ * then on all systems we deal with, at least the lower three bits
+ * of the pointer will always be clear.  Since @c unordered_map
+ * uses a bucket-hash scheme, this means that only 1/8 of the buckets
+ * will be used in such a case, resulting in lower efficiency.
+ *
+ * Here, we try to avoid this problem.
+ */
+struct ptrhash
+{
+  std::size_t operator() (const void* p) const
+  {
+    std::size_t x = reinterpret_cast<std::size_t> (p);
+    return (x>>3) ^ (x&7);
+  }
+};
+
+
+} // namespace SG
+
+
+#endif // not SGTOOLS_PTRHASH_H
diff --git a/Control/SGTools/SGTools/safe_clid.h b/Control/SGTools/SGTools/safe_clid.h
new file mode 100755
index 0000000000000000000000000000000000000000..ff48a1d7a33cef896e4b53557db3f816ad7b16f0
--- /dev/null
+++ b/Control/SGTools/SGTools/safe_clid.h
@@ -0,0 +1,58 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: safe_clid.h,v 1.2 2005-11-08 22:01:30 ssnyder Exp $
+
+/**
+ * @file  SGTools/safe_clid.h
+ * @author scott snyder
+ * @date Nov 2005
+ * @brief Find the class ID of a type, without triggering an error
+ *        if it isn't defined.
+ *
+ * The general interface for finding the class ID for some type @a T
+ * is to use @a ClassID_traits<T>::ID().  However, if no class ID
+ * has been defined for @a T, this will result in a compilation error.
+ * In some cases, where the class ID can be considered optional, this
+ * can severely restrict the applicability of generic code.
+ *
+ * This header provides @a SG::safe_clid<T>(), which should return
+ * the class ID of @T, or @a CLID_NULL if @a T does not have a defined
+ * class ID (without causing an error).
+ *
+ * The implementation relies on the fact that when the class ID traits
+ * class gets specialized for a specific class ID, it defines
+ * @a has_classID_tag.  The @a CLASS_DEF macro makes this definition,
+ * but if you specialize @a ClassID_traits yourself, you must remember
+ * to include @a has_classID_tag, or this function won't work.
+ */
+
+#ifndef SGTOOLS_SAFECLID_H
+#define SGTOOLS_SAFECLID_H
+
+
+#include "GaudiKernel/ClassID.h"
+
+
+namespace SG {
+
+
+/**
+ * @brief Return the class ID of @a T, or @a CLID_NULL if it doesn't
+ *        have one.  Avoids compilation errors if the class ID
+ *        is not defined.
+ */
+template <class T>
+CLID safe_clid();
+
+
+} // namespace SG
+
+
+#include "SGTools/safe_clid.icc"
+
+
+#endif // not SGTOOLS_SAFECLID_H
diff --git a/Control/SGTools/SGTools/safe_clid.icc b/Control/SGTools/SGTools/safe_clid.icc
new file mode 100755
index 0000000000000000000000000000000000000000..8645a886bfac7f33dd47eb5f9b103f6f79290a4d
--- /dev/null
+++ b/Control/SGTools/SGTools/safe_clid.icc
@@ -0,0 +1,121 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: safe_clid.icc,v 1.2 2007-12-14 03:12:34 binet Exp $
+/**
+ * @file  SGTools/safe_clid.icc
+ * @author scott snyder
+ * @date Nov 2005
+ * @brief Find the class ID of a type, without triggering an error
+ *        if it isn't defined.
+ *        Implementation file.
+ */
+
+#include "SGTools/ClassID_traits.h"
+#include "AthenaKernel/tools/type_tools.h"
+#include "boost/type_traits/remove_pointer.hpp"
+
+
+namespace SG {
+
+
+//-------------------------------------------------------------------------
+// Here's the first part.  @a safe_clid has the job of calling one of the
+// two @a safe_clid_1 overrides, depending on the state of the traits
+// class @a has_classID_tag definition.  We want the first one to be called
+// when @a has_classID_tag is @a true_tag, and the second to be called
+// in other cases (including the possibility that the typedef does not exist).
+// There are three possibilities to consider.
+//
+//   1. The traits class defines @a has_classID_tag as @a true_tag.
+//      Here, both decl 1 and 2 match the call.  It turns out
+//      that we can't use partial ordering to discriminate between
+//      these two on the basis of the tag (second) argument alone.
+//      That's the purpose of the first (dummy) argument.  By making
+//      it a pointer in decl 1 and completely generic in decl 2,
+//      we ensure that decl 1 is a more specific match when both
+//      decls are allowed.
+//
+//   2. The traits class defines @a has_classID_tag as something
+//      other than @a true_tag.  In this case, decl 1 doesn't match
+//      the call, but decl 2 will.  So decl 2 will be called.
+//
+//   3. The traits class has no definition for @a has_classID_tag.
+//      In this case, the type named in decl 1 does not exist.
+//      However, that is @e not an error --- it just means that
+//      decl 1 won't be considered as a candidate overload.
+//      (Look up ``substitution failure is not an error'' (SFINAE).)
+//      So again, decl 2 gets called.  Note that the requirement
+//      to handle this case (which comes about because the unspecialized
+//      version of @a ClassID_traits does not define this typedef)
+//      is why this may look backwards, using @a true_tag in the call,
+//      and the traits class typedef in the argument.
+
+
+// Decl 1
+template <class T>
+CLID safe_clid_1 (T*, typename ClassID_traits<T>::has_classID_tag);
+
+// Decl 2
+template <class T, class U>
+CLID safe_clid_1 (T, U);
+
+// This is the public entry point.
+template <class T>
+CLID safe_clid()
+{
+  return safe_clid_1 ((T*)0, type_tools::true_tag());
+}
+
+
+//-------------------------------------------------------------------------
+// Here is the definition for decl 1.  This gets called when the
+// traits class defines @a has_classID_tag as @a true_tag.
+// So we can go ahead and ask for the ID in this case.
+
+template <class T>
+CLID safe_clid_1 (T*, typename ClassID_traits<T>::has_classID_tag)
+{
+  return ClassID_traits<T>::ID();
+}
+
+
+//-------------------------------------------------------------------------
+// Here is the definition for decl 2.  This gets called when the traits
+// class does not define @a has_classID_tag is @a true_tag.
+// But there is one further decision to be made.  If @a T derives
+// from @a DataObject, then we can still get the class ID.
+// Otherwise, we must return @a CLID_NULL.
+
+// This is called if @a T does not derive from @a DataObject.
+// Return @a CLID_NULL.
+template <class T, bool B>
+struct safe_clid_2
+{
+  static CLID clid() { return CLID_NULL; }
+};
+
+// This specialization is used if @a T does derive from @a DataObject.
+// This returns the class ID.
+template <class T>
+struct safe_clid_2<T, true>
+{
+  static CLID clid() { return ClassID_traits<T>::ID(); }
+};
+
+// This is the definition corresponding to decl 2 above.
+// We test @a s_isDataObject in the traits class.
+// Note that here @a T will be a pointer to the class we're
+// actually interested in, so we need to strip a pointer.
+template <class T, class U>
+CLID safe_clid_1 (T, U)
+{
+  typedef typename boost::remove_pointer<T>::type typ;
+  return safe_clid_2<typ, ClassID_traits<typ>::s_isDataObject>::clid();
+}
+
+
+} // namespace SG
+
+
diff --git a/Control/SGTools/SGTools/selection.xml b/Control/SGTools/SGTools/selection.xml
new file mode 100755
index 0000000000000000000000000000000000000000..8cad941dc6b490e4917dd3df7bf62b3797d7754e
--- /dev/null
+++ b/Control/SGTools/SGTools/selection.xml
@@ -0,0 +1,12 @@
+<lcgdict>
+  <class name="IProxyDictWithPool" />
+  <class name="IStringPool" />
+  <class name="DataBucketBase" />
+  <class name="SG::DataProxy" />
+  <exclusion>
+    <class pattern="*iterator*tuple*long*unsigned*int*"/>
+  </exclusion>
+  <class name="std::vector<SG::DataProxy*>" />
+  <class name="std::vector<const SG::DataProxy*>" />
+  <class name="SG::BaseInfoBase" />
+</lcgdict>
diff --git a/Control/SGTools/SGTools/unordered_map.h b/Control/SGTools/SGTools/unordered_map.h
new file mode 100755
index 0000000000000000000000000000000000000000..8478446f5cd8d6b20d64dbd71dd2eea653fda4c1
--- /dev/null
+++ b/Control/SGTools/SGTools/unordered_map.h
@@ -0,0 +1,15 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: unordered_map.h,v 1.2 2008-09-17 01:17:05 binet Exp $
+#ifndef SGTOOLS_UNORDERED_MAP_H
+#define SGTOOLS_UNORDERED_MAP_H 1
+
+#ifndef CXXUTILS_UNORDERED_MAP_H
+ #include "CxxUtils/unordered_map.h"
+#endif
+
+#endif /* !SGTOOLS_UNORDERED_MAP_H */
diff --git a/Control/SGTools/cmt/requirements b/Control/SGTools/cmt/requirements
new file mode 100755
index 0000000000000000000000000000000000000000..782b742d6706d5a239135b62b1799e7ab86d36f1
--- /dev/null
+++ b/Control/SGTools/cmt/requirements
@@ -0,0 +1,44 @@
+package SGTools
+author Paolo Calafiura   <Paolo.Calafiura@cern.ch>
+author Srini Rajagopalan <srinir@bnl.gov>
+
+use AtlasPolicy    AtlasPolicy-*
+
+use CxxUtils	   CxxUtils-*	       Control	
+use AthenaKernel   AthenaKernel-*      Control
+
+#need IAddressProvider.h, IResetable.h
+
+use AtlasBoost     AtlasBoost-*	       External
+use GaudiInterface GaudiInterface-*    External
+
+library SGTools *.cxx 
+apply_pattern installed_library 
+
+private
+# Get the boost threads dso linked.
+macro_append Boost_linkopts $(Boost_linkopts_thread)
+macro_append SGTools_shlibflags $(Boost_linkopts)
+
+use SGAudCore 	   SGAudCore-*	       Control/SGMon
+use TestTools	   TestTools-*         AtlasTest
+use AtlasReflex    AtlasReflex-*       External  -no_auto_imports
+
+apply_pattern lcgdict dict=SGTools selectionfile=selection.xml headerfiles="-s=${SGTools_root}/SGTools SGToolsDict.h"
+
+apply_pattern UnitTest_run unit_test=CLIDRegistry
+apply_pattern UnitTest_run unit_test=VersionedKey
+apply_pattern UnitTest_run unit_test=DataBucket \
+  extrapatterns="^HistogramPersis.* INFO"
+apply_pattern UnitTest_run unit_test=BaseInfo
+apply_pattern UnitTest_run unit_test=safe_clid
+apply_pattern UnitTest_run unit_test=crc64
+apply_pattern UnitTest_run unit_test=exceptions
+apply_pattern UnitTest_run unit_test=StringPool
+apply_pattern UnitTest_run unit_test=ClassName
+apply_pattern UnitTest_run unit_test=DataProxy
+apply_pattern UnitTest_run unit_test=DataStore
+apply_pattern UnitTest_run unit_test=TransientAddress
+
+macro_append DOXYGEN_INPUT " ../doc"
+end_private
diff --git a/Control/SGTools/doc/MainPage.h b/Control/SGTools/doc/MainPage.h
new file mode 100755
index 0000000000000000000000000000000000000000..6e9bb51c0e925b83b5df61ee0c3fc277ac2a868b
--- /dev/null
+++ b/Control/SGTools/doc/MainPage.h
@@ -0,0 +1,29 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+
+@mainpage
+
+This package contains implementation classes for StoreGate.
+
+@section uses Packages used
+
+@htmlinclude used_packages.html
+
+@section requirements requirements 
+
+@include requirements
+
+@section refs More Documentation
+
+More information is available from the Athena wiki 
+<https://twiki.cern.ch/twiki/bin/view/Atlas/StoreGate>
+
+The code can be browsed using LXR 
+(http://alxr.usatlas.bnl.gov/lxr/source/atlas/Control/SGTools/)
+
+
+@author Paolo Calafiura <Paolo.Calafiura@cern.ch>
+*/
diff --git a/Control/SGTools/ispellwords b/Control/SGTools/ispellwords
new file mode 100644
index 0000000000000000000000000000000000000000..a82d919b9c09d0ce345ab9e235e0750275080618
--- /dev/null
+++ b/Control/SGTools/ispellwords
@@ -0,0 +1,527 @@
+personal_ws-1.1 en 342
+updateItemList
+decls
+addSymLink
+clid
+resetOnly
+requestRelease
+DataBucketCast
+EventHeader
+cmt
+SGAudCore
+theApp
+CLIDSvc
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+SGToolsDict
+StoreGateSvc
+SGTools
+bool
+bla
+Bleah
+blu
+Vukotic
+ProxyMap
+proxymap
+toObjectType
+dbbObject
+pSGAudSvc
+LXR
+StreamBuffer
+asStorable
+Leggett
+CxxUtils
+crc
+NoBase
+builtins
+cxx
+utils
+addAlias
+rawVersionKey
+FCA
+Calafiura
+DataObjects
+symlinks
+symLinks
+symlinked
+symLinked
+castTo
+cassert
+typeinfoName
+speeded
+IOA
+addInit
+addint
+CLASSVERSION
+malloc
+DataList
+initGaudi
+endcode
+AtlasBoost
+hpp
+StorableConversions
+SGIFolder
+SGFolder
+pDObj
+MyDataObj
+getMessageSvc
+printf
+gcc
+getAddress
+IProxyDictWithPool
+pRange
+Quarrie
+DataModel
+symlink
+DataHandles
+ctor
+gaudi
+cout
+gdo
+typedef'd
+pObj
+MyKey
+BaseInfoBase
+substr
+mem
+ajsdla
+StorageType
+TransientAddress
+NN
+Nuno
+accessData
+msg
+ns
+pok
+TestTools
+poly
+unsetInput
+regbase
+retrieveAllVersions
+pre
+StatusCode
+dbb
+modifs
+DataHeaderElement
+SG
+sg
+circ
+DF
+timespec
+setAlias
+DHE
+rhs
+ClassID
+classID
+wrt
+ItemList
+CLIDs
+CLID's
+clids
+refcount
+refCount
+Xed
+xd
+AbstractDataObj
+dp
+dep
+createObj
+InputDataHeader
+dtor
+TrEMBL
+Gemmeren
+AbstractType
+BaseInfoBaseImpl
+setDefaults
+lkjasd
+lkajsd
+VK
+vkey
+wiki
+AthenaKernel
+persistency
+AddressProvider
+typeinfo
+paks
+mutex
+StringPool
+CLIDComps
+MacOSX
+outputLevel
+typeName
+copyVK
+pMap
+pmap
+IStringPool
+VersionedKey
+CallBackID
+behaviour
+metafunction
+pointee
+setClid
+converterTo
+IConversionSvc
+stdout
+stringToKey
+DataBucket
+DataSvc
+param
+stateFlag
+const
+vtable
+IOVSvc
+hashtable
+AtlasReflex
+svcLocator
+SGVersionedKey
+templated
+isInput
+dobjs
+fromStorable
+DBDataModel
+ptr
+DataObj
+SFINAE
+dobj
+DataBucketTraitFwd
+genreflex
+DataBucketBase
+StlVectorClids
+registerKey
+MessageSvc
+relPool
+ClassName
+Binet
+binet
+castObject
+BuiltinsClids
+sgkey
+ProxyProvider
+InterfaceID
+INITIALCRC
+SLC
+GaudiKernel
+DEFS
+scott
+CLASSDEF
+DataHeader
+cptr
+getPrimaryClassID
+clearStore
+everything's
+snyder
+ssnyder
+decl
+doxygen
+SGComps
+aspdk
+CLIDREG
+castfnTo
+outObject
+dquarrie
+DataStore
+FIXME
+forceRemove
+dict
+src
+tinfo
+DLT
+demangled
+refcounting
+valgrind
+Stl
+DEFAULTKEY
+refcounts
+str
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+clearAddress
+DATAVECTOR
+DataVector
+StatusCodeSvc
+SWISSPROT
+CLIDRegistry
+namespace
+aliasKey
+typeid
+Schaffer
+schaffer
+inlined
+chkconfig
+DataBucketTrait
+tryELRemap
+tdef
+Storable
+storable
+Rajagopalan
+impl
+castfn
+CreateSvc
+IPageAccessControlSvc
+toType
+INLINE
+func
+SGAudSvc
+IOpaqueAddress
+objName
+ISGAudSvc
+EventSelectorAthenaPool
+html
+baseinfo
+BaseInfo
+IProxyRegistry
+icc
+arg
+eg
+i'll
+ULL
+noAudSvc
+pObject
+API
+FdB
+IID
+atoi
+irt
+ElementLink
+resetFlag
+MAXCLID
+pgref
+vkeys
+addEntry
+BaseInfoImpl
+readback
+keyToString
+MINCLID
+strlen
+eval
+indep
+converterToHelper
+StoreGate
+struct
+iostream
+ints
+versionKey
+StoreMap
+pMember
+BaseType
+IRegisterTransient
+Versioned
+mixup
+ClassIDSvc
+IMessageSvcHolder
+SAFECLID
+ECMA
+SGFolderItem
+retrieveHighestVersion
+Ilija
+args
+IRegistry
+initlist
+removeProxy
+enum
+GaudiDataObj
+uint
+init
+DataProxy
+inObject
+consultProvider
+isDataObject
+libSGTools
+IProxyDict
+ptrhash
+htmlinclude
+setProperty
+IDC
+DataObject
+mainpage
+calaf
+CGL
+asd
+StorableConversion
+pRegister
+STLMAPCLIDS
+StlMapClids
+addr
+laskjkd
+t2pmap
+T2pMap
+typedef
+instantiation
+doesn
+v1r19
+v19
+v16
+crc64addint
+gcc4
+lookup
+casted
+SLC4
+typedefs
+t2pRegister
+t2p
+ispellwords
+addToStore
+IResetable
+runtime
+RegisterAddBaseInit
+keyless
+Kittelmann
+reinit
+setTransientAddress
+errNo
+errno
+checkreq
+d3pds
+defaultkey
+isConst
+bools
+DataHandleBase
+DataHandle
+resized
+ulonglong
+ulong
+ushort
+uint8
+vec
+savannah
+cacheable
+updateAddress
+isValid
+storeID
+gcc43
+coverity
+SGImplSvc
+Paolo
+wscript
+Sebastien
+sz
+dst
+MyType
+MyCopyConversion
+Base3
+Base2
+Base1
+instantiations
+B3
+B2
+B1
+BASES3
+BASES2
+BASES1
+isn
+Destructor
+CopyConversionBase
+cnv
+initializations
+initializer
+recurse
+AddBaseInfo
+ourself
+ARG2
+ARG1
+DEF2
+accessors
+0x
+decrement
+fwk
+itr1
+ok
+T2PMap
+EL
+02u
+ost
+aren
+CRC64
+unordered
+unspecialized
+HistogramPersis
+DynamicType
+dataPointer
+typeless
+itrEnd
+itr
+GaudiObject
+resettable
+nmatch
+crc64
+0xd800000000000000ULL
+POLY64REV
+0x0000000000000000ULL
+08X
+test1
+test2
+fooB
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+C874767DA8254746
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+2DF1AA17420FCA3F
+NoAuxStore
+AuxStore
+CLASSAUXSTORE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+dicts
+AthContainers
+AthContainersInterfaces
+leggett
+charles
+setSGKey
+setID
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+pTAd
+addRef
+key2
+key3
+key4
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+setStore
+clID
+tAddr
+ims
+gLog
+MsgStream
+endreq
+queryInterface
+pTransient
+proxy1
+proxy2
+proxy3
+exact1
+keyToString1
+keyToString2
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+ExcBadDataProxyCast
+keyMap
+storeMap
+tid
+dummied
+shouldn
+ExcProxyCollision
+dp1
+dp2
+dp1a
+dp1b
+dpx
+dp3
+typeCount
+tRange
+proxyList
+dp4
+dp1x
+pac
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+abc
diff --git a/Control/SGTools/share/BaseInfo_test.ref b/Control/SGTools/share/BaseInfo_test.ref
new file mode 100755
index 0000000000000000000000000000000000000000..bae42c55f9e0a4e297a4d197d8aadfe147ef269b
--- /dev/null
+++ b/Control/SGTools/share/BaseInfo_test.ref
@@ -0,0 +1,2 @@
+test1
+test2
diff --git a/Control/SGTools/share/CLIDRegistry_test.ref b/Control/SGTools/share/CLIDRegistry_test.ref
new file mode 100755
index 0000000000000000000000000000000000000000..b5d0b6a45586b001a89587f8568a2ad420c975ae
--- /dev/null
+++ b/Control/SGTools/share/CLIDRegistry_test.ref
@@ -0,0 +1,2 @@
+*** CLIDRegistry_test starts ***
+*** CLIDRegistry_test OK ***
diff --git a/Control/SGTools/share/ClassName_test.ref b/Control/SGTools/share/ClassName_test.ref
new file mode 100755
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/Control/SGTools/share/DataBucket_test.ref b/Control/SGTools/share/DataBucket_test.ref
new file mode 100755
index 0000000000000000000000000000000000000000..1c572a185bb194cc452b59a4a31fe306ec409251
--- /dev/null
+++ b/Control/SGTools/share/DataBucket_test.ref
@@ -0,0 +1,48 @@
+ApplicationMgr    SUCCESS 
+====================================================================================================================================
+                                                   Welcome to ApplicationMgr (GaudiCoreSvc v999r999)
+                                          running on karma on Thu Apr 17 17:22:20 2014
+====================================================================================================================================
+ApplicationMgr       INFO Application Manager Configured successfully
+EventLoopMgr      WARNING Unable to locate service "EventSelector" 
+EventLoopMgr      WARNING No events will be processed from external input.
+HistogramPersis...WARNING Histograms saving not required.
+ApplicationMgr       INFO Application Manager Initialized successfully
+ApplicationMgr Ready
+int has_classID 244260744 version 1 and does not inherit from DataObject
+const int* has_classID 244260744
+vector<int> has_classID 22592129
+GaudiDataObj has_classID 8010 and does inherit from DataObject
+MyDataObj has_classID 8000 and does not inherit from DataObject
+AbstractDataObj has_classID 8011
+AbstractType has_classID 8004
+Now we expect to see an error message:
+----Error Message Starts--->>
+SG::fromStorable  WARNING can't convert stored DataObject 0x1c33120 to type (WrongType)
+ Unless you are following a symlink, it probably means you have a duplicate CLID = 8000
+<<---Error Message Ends-------
+Now we expect to see an error message:
+----Error Message Starts--->>
+SG::fromStorable  WARNING can't convert stored DataObject 0x1c33120 to type (WrongType)
+ Unless you are following a symlink, it probably means you have a duplicate CLID = 8000
+<<---Error Message Ends-------
+Now we expect to see an error message:
+----Error Message Starts--->>
+SG::fromStorable  WARNING null input pointer 
+<<---Error Message Ends-------
+Now we expect to see an error message:
+----Error Message Starts--->>
+SG::fromStorable  WARNING can't convert stored DataObject 0x1c33120 to type (WrongType)
+ Unless you are following a symlink, it probably means you have a duplicate CLID = 8010
+<<---Error Message Ends-------
+Now we expect to see an error message:
+----Error Message Starts--->>
+SG::fromStorable  WARNING can't convert stored DataObject 0x1e61c00 to type (WrongType)
+ Unless you are following a symlink, it probably means you have a duplicate CLID = 8010
+<<---Error Message Ends-------
+test2
+SG::fromStorable  WARNING can't convert stored DataObject 0x1c33120 to type (X3)
+ Unless you are following a symlink, it probably means you have a duplicate CLID = 8011
+test3
+lock
+*** DataBucket_test OK ***
diff --git a/Control/SGTools/share/DataProxy_test.ref b/Control/SGTools/share/DataProxy_test.ref
new file mode 100644
index 0000000000000000000000000000000000000000..6a50354f32c714982bf1734756bcfe5b8f21d32a
--- /dev/null
+++ b/Control/SGTools/share/DataProxy_test.ref
@@ -0,0 +1,4 @@
+test1
+test2
+lock
+lock
diff --git a/Control/SGTools/share/DataStore_test.ref b/Control/SGTools/share/DataStore_test.ref
new file mode 100644
index 0000000000000000000000000000000000000000..6c942137c7273360a9dc36c067f4c3d08485b93b
--- /dev/null
+++ b/Control/SGTools/share/DataStore_test.ref
@@ -0,0 +1,15 @@
+test_ctor
+test_addToStore
+test_addAlias
+test_addSymLink
+test_proxy_exact
+test_proxy
+test_typeCount
+test_tRange
+test_pRange
+test_proxyList
+test_keys
+test_removeProxy
+test_clearStore
+test_t2p
+test_dummy
diff --git a/Control/SGTools/share/StringPool_test.ref b/Control/SGTools/share/StringPool_test.ref
new file mode 100755
index 0000000000000000000000000000000000000000..94db96eba5c6144cacb615a17106269685c6e21a
--- /dev/null
+++ b/Control/SGTools/share/StringPool_test.ref
@@ -0,0 +1,13 @@
+000000003FFFFFFF 
+000000000FD9252C MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+000000000EE07ECA MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+000000000AC0B3E3 ajsdla lkjasd lkjasd 
+000000003979421C paks  aspdk pok  asd
+000000001B269909 asd  laskjkd lkajsd
+pool dump
+          3fffffff         0 
+           ac0b3e3         3 ajsdla lkjasd lkjasd 
+           ee07eca         2 MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+          3979421c         4 paks  aspdk pok  asd
+           fd9252c         1 MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE
+          1b269909         5 asd  laskjkd lkajsd
diff --git a/Control/SGTools/share/TransientAddress_test.ref b/Control/SGTools/share/TransientAddress_test.ref
new file mode 100644
index 0000000000000000000000000000000000000000..204dae5613b633357b85b6b559c02a5aa7ff836d
--- /dev/null
+++ b/Control/SGTools/share/TransientAddress_test.ref
@@ -0,0 +1,7 @@
+test1
+addRef 1 1
+addRef 2 1
+release 1 0
+release 2 0
+addRef 2 1
+release 2 0
diff --git a/Control/SGTools/share/VersionedKey_test.ref b/Control/SGTools/share/VersionedKey_test.ref
new file mode 100644
index 0000000000000000000000000000000000000000..dcbda6f6b4c0a07fbf23caa99f409a16abfa40a7
--- /dev/null
+++ b/Control/SGTools/share/VersionedKey_test.ref
@@ -0,0 +1,3 @@
+Versioned Key 1=;01;bla
+Versioned Key 2=;99;Bleah
+Versioned Key 3=;00;default
diff --git a/Control/SGTools/share/crc64_test.ref b/Control/SGTools/share/crc64_test.ref
new file mode 100755
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/Control/SGTools/share/exceptions_test.ref b/Control/SGTools/share/exceptions_test.ref
new file mode 100644
index 0000000000000000000000000000000000000000..d3ec4082a460e8ae3e296c744065e41f35936c83
--- /dev/null
+++ b/Control/SGTools/share/exceptions_test.ref
@@ -0,0 +1,3 @@
+test1
+Bad cast of DataProxy with CLID 123 to type int
+ExcProxyCollision: proxy collision for clid/key 123 / abc (primary 456 / def).
diff --git a/Control/SGTools/share/safe_clid_test.ref b/Control/SGTools/share/safe_clid_test.ref
new file mode 100755
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/Control/SGTools/src/BaseInfo.cxx b/Control/SGTools/src/BaseInfo.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..f298359fd11da68be75fdbaa749bddfb02f972f6
--- /dev/null
+++ b/Control/SGTools/src/BaseInfo.cxx
@@ -0,0 +1,695 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: BaseInfo.cxx,v 1.9 2008-11-25 21:45:04 ssnyder Exp $
+/**
+ * @file  SGTools/BaseInfo.cxx
+ * @author scott snyder
+ * @date Nov 2005
+ * @brief Provide an interface for finding inheritance information
+ *        at run time.
+ *        Out-of-line implementation.
+ */
+
+#include "SGTools/BaseInfo.h"
+//#include "boost/thread/mutex.hpp"
+#include <map>
+
+
+namespace SG {
+
+
+struct BaseInfoBaseImpl {
+  /// Structure to hold information about one base.
+  struct info {
+    /// Constructor.  @a converter* and @a is_virtual are as for @a add_info.
+    info (BaseInfoBase::castfn_t* converter = 0,
+          BaseInfoBase::castfn_t* converterTo = 0,
+          bool is_virtual = false);
+
+    /// Converter function.  Takes a @a T* and converts to a pointer
+    /// to this base.
+    BaseInfoBase::castfn_t* m_converter;
+
+    /// Converter function.  Takes a pointer to this base and converts
+    /// to @a T*.
+    /// to this base.
+    BaseInfoBase::castfn_t* m_converterTo;
+
+    /// True if the derivation from this base to @a T is via
+    /// virtual derivation.
+    bool m_is_virtual;
+  };
+
+
+  /// CLID of this class.
+  CLID m_clid;
+
+  /// Set to true when first created.
+  /// Reset after we scan for init functions.
+  bool m_needs_init;
+
+  /// @c std::type_info of this class.
+  const std::type_info* m_typeinfo;
+
+
+  /// Hold base information indexed by class ID.
+  typedef std::map<CLID, info> clid_map_type;
+  clid_map_type m_clidmap;
+
+  /// Hold base information indexed by @a type_info.
+  typedef std::map<const std::type_info*, info> ti_map_type;
+  ti_map_type m_timap;
+
+
+  /// Map of all CLIDs to @c BaseInfoBase instances.
+  typedef std::map<CLID, BaseInfoBase*> bi_by_clid_map_type;
+  static bi_by_clid_map_type* s_bi_by_clid;
+
+  /// Map of all @c type_info names to @c BaseInfoBase instances.
+  typedef std::map<const std::type_info*, BaseInfoBase*> bi_by_ti_map_type;
+  static bi_by_ti_map_type* s_bi_by_ti;
+
+
+  /// Hold copy conversion information indexed by class ID.
+  typedef std::map<CLID, const CopyConversionBase*> clid_copyconversion_type;
+  clid_copyconversion_type m_clid_copyconversion_map;
+
+  /// Hold copy conversion information indexed by @ type_info.
+  typedef std::map<const std::type_info*, const CopyConversionBase*> 
+    ti_copyconversion_type;
+  ti_copyconversion_type m_ti_copyconversion_map;
+
+  /// Holds @c BaseInfo classes awaiting initialization.
+  /// This is used to defer initialization until everything's loaded.
+  struct init_elem_t {
+    CLID m_clid;
+    const std::type_info* m_ti;
+    BaseInfoBase::init_func_t* m_init_func;
+  };
+  static std::vector<init_elem_t>* s_init_list;
+
+
+  // To make sure that the maps get deleted at program termination.
+  struct Deleter {
+    ~Deleter();
+  };
+  static Deleter s_deleter;
+
+  /// For thread-safety.
+  //static boost::mutex s_mutex;
+};
+
+
+
+/**
+ * @brief Return the CLID for this class.
+ */
+CLID BaseInfoBase::clid() const
+{
+  return m_impl->m_clid;
+}
+
+
+/**
+ * @brief Return the @c std::type_info for this class.
+ */
+const std::type_info& BaseInfoBase::typeinfo() const
+{
+  return *m_impl->m_typeinfo;
+}
+
+
+/**
+ * @brief Cast to a base pointer.
+ * @param p The pointer to cast (a @a T* cast to a @a void*).
+ * @param clid ID of the class to which to cast.
+ * @return The pointer cast to the requested type, returned
+ *         as a @a void*.  @a clid must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ */
+void* BaseInfoBase::cast (void* p, CLID clid) const
+{
+  const BaseInfoBaseImpl::clid_map_type& map = m_impl->m_clidmap;
+  BaseInfoBaseImpl::clid_map_type::const_iterator i = map.find (clid);
+  if (i != map.end())
+    return i->second.m_converter (p);
+  return 0;
+}
+
+
+/**
+ * @brief Cast to a base pointer.
+ * @param p The pointer to cast (a @a T* cast to a @a void*).
+ * @param clid @a type_info of the class to which to cast.
+ * @return The pointer cast to the requested type, returned
+ *         as a @a void*.  @a tinfo must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ */
+void* BaseInfoBase::cast (void* p, const std::type_info& tinfo) const
+{
+  const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap;
+  BaseInfoBaseImpl::ti_map_type::const_iterator i = map.find (&tinfo);
+  if (i != map.end())
+    return i->second.m_converter (p);
+  return 0;
+}
+
+
+/**
+ * @brief Cast to a derived pointer.
+ * @param p The pointer to cast (a @a B* cast to a @a void*).
+ * @param clid ID of the class @a B from which to cast.
+ * @return The pointer cast to the requested type, returned
+ *         as a @a void*.  @a clid must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ *         0 will also be returned if the @a dynamic_cast fails.
+ */
+void* BaseInfoBase::castTo (void* p, CLID clid) const
+{
+  const BaseInfoBaseImpl::clid_map_type& map = m_impl->m_clidmap;
+  BaseInfoBaseImpl::clid_map_type::const_iterator i = map.find (clid);
+  if (i != map.end() && i->second.m_converterTo)
+    return i->second.m_converterTo (p);
+  return 0;
+}
+
+
+/**
+ * @brief Cast to a derived pointer.
+ * @param p The pointer to cast (a @a B* cast to a @a void*).
+ * @param clid @a type_info of the class @a B from which to cast.
+ * @return The pointer cast to the requested type, returned
+ *         as a @a void*.  @a tinfo must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ *         0 will also be returned if the @a dynamic_cast fails.
+ */
+void* BaseInfoBase::castTo (void* p, const std::type_info& tinfo) const
+{
+  const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap;
+  BaseInfoBaseImpl::ti_map_type::const_iterator i = map.find (&tinfo);
+  if (i != map.end() && i->second.m_converterTo)
+    return i->second.m_converterTo (p);
+  return 0;
+}
+
+
+/**
+ * @brief Return a function for casting to a base pointer.
+ * @param clid ID of the class to which to cast.
+ * @return A function to convert a pointer to a @c T to a pointer
+ *         to the type identified by @a clid.
+ *         @a clid must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ */
+BaseInfoBase::castfn_t* BaseInfoBase::castfn (CLID clid) const
+{
+  const BaseInfoBaseImpl::clid_map_type& map = m_impl->m_clidmap;
+  BaseInfoBaseImpl::clid_map_type::const_iterator i = map.find (clid);
+  if (i != map.end())
+    return i->second.m_converter;
+  return 0;
+}
+
+
+/**
+ * @brief Return a function for casting to a base pointer.
+ * @param clid @a type_info of the class to which to cast.
+ * @return A function to convert a pointer to a @c T to a pointer
+ *         to the type identified by @a tinfo.
+ *         @a tinfo must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ */
+BaseInfoBase::castfn_t*
+BaseInfoBase::castfn (const std::type_info& tinfo) const
+{
+  const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap;
+  BaseInfoBaseImpl::ti_map_type::const_iterator i = map.find (&tinfo);
+  if (i != map.end())
+    return i->second.m_converter;
+  return 0;
+}
+
+
+/**
+ * @brief Return a function for casting to a derived pointer.
+ * @param clid ID of the class @a B from which to cast.
+ * @return A function to convert a pointer to a @a B to a pointer
+ *         to a @a T.  @a B must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ *         0 will also be returned if the @a dynamic_cast fails.
+ */
+BaseInfoBase::castfn_t* BaseInfoBase::castfnTo (CLID clid) const
+{
+  const BaseInfoBaseImpl::clid_map_type& map = m_impl->m_clidmap;
+  BaseInfoBaseImpl::clid_map_type::const_iterator i = map.find (clid);
+  if (i != map.end())
+    return i->second.m_converterTo;
+  return 0;
+}
+
+
+/**
+ * @brief Return a function for casting to a derived pointer.
+ * @param clid @a type_info of the class @a B from which to cast.
+ * @return A function to convert a pointer to a @a B to a pointer
+ *         to a @a T.  @a B must be known to be a base
+ *         of @a T; otherwise, 0 will be returned.
+ *         0 will also be returned if the @a dynamic_cast fails.
+ */
+BaseInfoBase::castfn_t*
+BaseInfoBase::castfnTo (const std::type_info& tinfo) const
+{
+  const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap;
+  BaseInfoBaseImpl::ti_map_type::const_iterator i = map.find (&tinfo);
+  if (i != map.end())
+    return i->second.m_converterTo;
+  return 0;
+}
+
+
+/**
+ * @brief Return the class IDs of all known bases of @a T (that
+ *        have class IDs).  The list will include @a T itself.
+ */
+std::vector<CLID> BaseInfoBase::get_bases() const
+{
+  const BaseInfoBaseImpl::clid_map_type& map = m_impl->m_clidmap;
+  std::vector<CLID> v;
+  v.reserve (map.size());
+  for (BaseInfoBaseImpl::clid_map_type::const_iterator i = map.begin();
+       i != map.end();
+       ++i)
+    v.push_back (i->first);
+  return v;
+}
+
+
+/**
+ * @brief Return the @c type_info's of all known bases of @a T.
+ *        The list will include @a T itself.
+ */
+std::vector<const std::type_info*> BaseInfoBase::get_ti_bases() const
+{
+  const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap;
+  std::vector<const std::type_info*> v;
+  v.reserve (map.size());
+  for (BaseInfoBaseImpl::ti_map_type::const_iterator i = map.begin();
+       i != map.end();
+       ++i)
+    v.push_back (i->first);
+  return v;
+}
+
+
+/**
+ * @brief Return true if @a clid is the ID of a class that
+ *        is known to be a base of @a T.  @a T is considered
+ *        to be its own base for this purpose.
+ * @param clid The ID of the class to test.
+ */
+bool BaseInfoBase::is_base (CLID clid) const
+{
+  const BaseInfoBaseImpl::clid_map_type& map = m_impl->m_clidmap;
+  BaseInfoBaseImpl::clid_map_type::const_iterator i = map.find (clid);
+  return i != map.end();
+}
+
+
+/**
+ * @brief Return true if @a tinfo is the @a type_info of a class that
+ *        is known to be a base of @a T.  @a T is considered
+ *        to be its own base for this purpose.
+ * @param clid The ID of the class to test.
+ */
+bool BaseInfoBase::is_base (const std::type_info& tinfo) const
+{
+  const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap;
+  BaseInfoBaseImpl::ti_map_type::const_iterator i = map.find (&tinfo);
+  return i != map.end();
+}
+
+
+/**
+ * @brief Return true if @a clid is the ID of a class that
+ *        is known to be a virtual base of @a T.  (This will always
+ *        be false for @a T itself.)
+ * @param clid The ID of the class to test.
+ */
+bool BaseInfoBase::is_virtual (CLID clid) const
+{
+  const BaseInfoBaseImpl::clid_map_type& map = m_impl->m_clidmap;
+  BaseInfoBaseImpl::clid_map_type::const_iterator i = map.find (clid);
+  if (i != map.end())
+    return i->second.m_is_virtual;
+  return false;
+}
+
+
+/**
+ * @brief Return true if @a tinfo is the @a std::type_info of a class that
+ *        is known to be a virtual base of @a T.  (This will always
+ *        be false for @a T itself.)
+ * @param tinfo The @a std::type_info of the class to test.
+ */
+bool BaseInfoBase::is_virtual (const std::type_info& tinfo) const
+{
+  const BaseInfoBaseImpl::ti_map_type& map = m_impl->m_timap;
+  BaseInfoBaseImpl::ti_map_type::const_iterator i = map.find (&tinfo);
+  if (i != map.end())
+    return i->second.m_is_virtual;
+  return false;
+}
+
+
+/**
+ * @brief Search for a copy conversion to @c tinfo.
+ * @param tinfo The class to which we want to convert.
+ *
+ * Returns the conversion instance or 0.
+ */
+const CopyConversionBase*
+BaseInfoBase::copy_conversion (const std::type_info& tinfo) const
+{
+  const BaseInfoBaseImpl::ti_copyconversion_type& map =
+    m_impl->m_ti_copyconversion_map;
+  BaseInfoBaseImpl::ti_copyconversion_type::const_iterator i =
+    map.find (&tinfo);
+  if (i != map.end())
+    return i->second;
+  return 0;
+}
+
+
+/**
+ * @brief Search for a copy conversion to @c clid.
+ * @param clid The class to which we want to convert.
+ *
+ * Returns the conversion instance or 0.
+ */
+const CopyConversionBase*
+BaseInfoBase::copy_conversion (CLID clid) const
+{
+  const BaseInfoBaseImpl::clid_copyconversion_type& map =
+    m_impl->m_clid_copyconversion_map;
+  BaseInfoBaseImpl::clid_copyconversion_type::const_iterator i =
+    map.find (clid);
+  if (i != map.end())
+    return i->second;
+  return 0;
+}
+
+
+/**
+ * @brief Add a new copy conversion.
+ * @param clid The @c CLID of the target class.
+ * @param tinfo The @c std::type_info of the target class.
+ * @param cnv A @c CopyConversionBase instance describing the conversion.
+ *
+ * The @c BaseInfoBase takes ownership of the @c cnv object.
+ */
+void
+BaseInfoBase::add_copy_conversion (CLID clid,
+                                   const std::type_info& tinfo,
+                                   const CopyConversionBase* cnv)
+{
+  if (clid != CLID_NULL)
+    m_impl->m_clid_copyconversion_map[clid] = cnv;
+  m_impl->m_ti_copyconversion_map[&tinfo] = cnv;
+}
+
+
+/**
+ * @brief Return known copy conversions.
+ *
+ * Returns the CLIDs of all target classes that have been registered
+ * with this one for copy conversion.
+ */
+std::vector<CLID>
+BaseInfoBase::get_copy_conversions() const
+{
+  std::vector<CLID> out;
+  out.reserve (m_impl->m_clid_copyconversion_map.size());
+  for (BaseInfoBaseImpl::clid_copyconversion_type::const_iterator it =
+         m_impl->m_clid_copyconversion_map.begin();
+       it != m_impl->m_clid_copyconversion_map.end();
+       ++it)
+  {
+    out.push_back (it->first);
+  }
+  return out;
+}
+
+
+/**
+ * @brief Add information about one base class.
+ * @param clid The class ID of the base.  May be @a CLID_NULL if no
+ *             class ID is available.
+ * @param tinfo The @a std::type_info of the base.
+ * @param converter Converter function.  This should be able to
+ *                  convert a @a T* to a pointer to this base.
+ * @param converterTo Converter function.  This should be able to
+ *                    convert a pointer to this base to a @a T*.
+ * @param is_virtual True if the derivation from this base to @a T
+ *                   is via virtual derivation.
+ */
+void BaseInfoBase::add_info (CLID clid,
+                             const std::type_info& tinfo,
+                             castfn_t* converter,
+                             castfn_t* converterTo,
+                             bool is_virtual)
+{
+  if (clid == CLID_NULL)
+    clid = clid_from_initlist (tinfo);
+  if (m_impl->m_timap.find (&tinfo) == m_impl->m_timap.end()) {
+    if (clid != CLID_NULL)
+      m_impl->m_clidmap[clid] =
+        BaseInfoBaseImpl::info (converter, converterTo, is_virtual);
+    m_impl->m_timap[&tinfo] =
+      BaseInfoBaseImpl::info (converter, converterTo, is_virtual);
+  }
+}
+
+
+/**
+ * @brief Convenience constructor.
+ * @param converter Converter function.  This should be able to
+ *                  convert a @a T* to a pointer to this base.
+ * @param converterTo Converter function.  This should be able to
+ *                    convert a pointer to this base to a @a T*.
+ * @param is_virtual True if the derivation from this base to @a T
+ *                   is via virtual derivation.
+ *
+ * The defaults are there just so this class can be used with STL
+ * containers that require a default ctor.
+ */
+BaseInfoBaseImpl::info::info (BaseInfoBase::castfn_t* converter /*= 0*/,
+                              BaseInfoBase::castfn_t* converterTo /*= 0*/,
+                              bool is_virtual /*= false*/)
+  : m_converter (converter),
+    m_converterTo (converterTo),
+    m_is_virtual (is_virtual)
+{
+}
+
+
+/**
+ * @brief Constructor.
+ * @param clid The class ID of this class.  May be @c CLID_NULL if no
+ *             ID is available.
+ * @param tinfo The @c std::type_info for this class.
+ */
+BaseInfoBase::BaseInfoBase (CLID clid, const std::type_info& tinfo)
+  : m_impl (new BaseInfoBaseImpl)
+{
+  if (clid == CLID_NULL)
+    clid = clid_from_initlist (tinfo);
+  m_impl->m_clid = clid;
+  m_impl->m_typeinfo = &tinfo;
+  m_impl->m_needs_init = true;
+
+  //boost::mutex::scoped_lock lock (BaseInfoBaseImpl::s_mutex);
+  if (!BaseInfoBaseImpl::s_bi_by_clid)
+    BaseInfoBaseImpl::s_bi_by_clid = new BaseInfoBaseImpl::bi_by_clid_map_type;
+  if (!BaseInfoBaseImpl::s_bi_by_ti)
+    BaseInfoBaseImpl::s_bi_by_ti   = new BaseInfoBaseImpl::bi_by_ti_map_type;
+
+  // Register this instance in the static maps.
+  if (clid != CLID_NULL)
+    (*BaseInfoBaseImpl::s_bi_by_clid)[clid] = this;
+  (*BaseInfoBaseImpl::s_bi_by_ti)[&tinfo] = this;
+}
+
+
+/**
+ * @brief Destructor.
+ */
+BaseInfoBase::~BaseInfoBase()
+{
+  for (BaseInfoBaseImpl::ti_copyconversion_type::iterator it =
+         m_impl->m_ti_copyconversion_map.begin();
+       it != m_impl->m_ti_copyconversion_map.end();
+       ++it)
+  {
+    delete it->second;
+  }
+  delete m_impl;
+}
+
+
+/**
+ * @brief Find the @c BaseInfoBase instance for @c clid.
+ * @param clid The class ID of the class for which we want information.
+ *
+ * Returns 0 if no @c BaseInfoBase instance is available.
+ */
+const BaseInfoBase* BaseInfoBase::find (CLID clid)
+{
+  //boost::mutex::scoped_lock lock (BaseInfoBaseImpl::s_mutex);
+  if (!BaseInfoBaseImpl::s_bi_by_clid) return 0;
+  BaseInfoBaseImpl::bi_by_clid_map_type::iterator i =
+    BaseInfoBaseImpl::s_bi_by_clid->find (clid);
+  if (i != BaseInfoBaseImpl::s_bi_by_clid->end()) {
+    if (!i->second->m_impl->m_needs_init)
+      return i->second;
+    i->second->m_impl->m_needs_init = false;
+  }
+
+  // Try the initlist.
+  if (BaseInfoBaseImpl::s_init_list) {
+    for (size_t j = 0; j < BaseInfoBaseImpl::s_init_list->size(); j++) {
+      if ((*BaseInfoBaseImpl::s_init_list)[j].m_clid == clid) {
+        BaseInfoBase::init_func_t* init = 
+          (*BaseInfoBaseImpl::s_init_list)[j].m_init_func;
+        BaseInfoBaseImpl::s_init_list->erase
+          (BaseInfoBaseImpl::s_init_list->begin() + j);
+        --j;
+        init();
+        i = BaseInfoBaseImpl::s_bi_by_clid->find (clid);
+      }
+    }
+  }
+  if (i != BaseInfoBaseImpl::s_bi_by_clid->end())
+    return i->second;
+
+  return 0;
+}
+
+
+/**
+ * @brief Find the @c BaseInfoBase instance for @c tinfo.
+ * @param tinfo The @c std::type_info of the class
+ *              for which we want information.
+ *
+ * Returns 0 if no @c BaseInfoBase instance is available.
+ */
+const BaseInfoBase* BaseInfoBase::find (const std::type_info& tinfo)
+{
+  //boost::mutex::scoped_lock lock (BaseInfoBaseImpl::s_mutex);
+  if (!BaseInfoBaseImpl::s_bi_by_ti) return 0;
+  BaseInfoBaseImpl::bi_by_ti_map_type::iterator i = 
+    BaseInfoBaseImpl::s_bi_by_ti->find (&tinfo);
+  if (i != BaseInfoBaseImpl::s_bi_by_ti->end()) {
+    if (!i->second->m_impl->m_needs_init)
+      return i->second;
+    i->second->m_impl->m_needs_init = false;
+  }
+
+  // Try the initlist.
+  if (BaseInfoBaseImpl::s_init_list) {
+    for (size_t j = 0; j < BaseInfoBaseImpl::s_init_list->size(); j++) {
+      if ((*BaseInfoBaseImpl::s_init_list)[j].m_ti == &tinfo) {
+        BaseInfoBase::init_func_t* init = 
+          (*BaseInfoBaseImpl::s_init_list)[j].m_init_func;
+        BaseInfoBaseImpl::s_init_list->erase
+          (BaseInfoBaseImpl::s_init_list->begin() + j);
+        --j;
+        init();
+        i = BaseInfoBaseImpl::s_bi_by_ti->find (&tinfo);
+      }
+    }
+  }
+  if (i != BaseInfoBaseImpl::s_bi_by_ti->end())
+    return i->second;
+
+  return 0;
+}
+
+
+/**
+ * @brief Register an initialization function.
+ * @param clid The class ID of the class being registered.
+ * @param tinfo The @c std::type_info for the class being registered.
+ * @param init_func Function to initialize @c BaseInfo for the class.
+ */
+void BaseInfoBase::addInit (CLID clid,
+                            const std::type_info* tinfo,
+                            init_func_t* init_func)
+{
+  //boost::mutex::scoped_lock lock (BaseInfoBaseImpl::s_mutex);
+  if (!BaseInfoBaseImpl::s_init_list)
+    BaseInfoBaseImpl::s_init_list =
+      new std::vector<BaseInfoBaseImpl::init_elem_t>;
+  BaseInfoBaseImpl::init_elem_t elem;
+  elem.m_clid = clid;
+  elem.m_ti = tinfo;
+  elem.m_init_func = init_func;
+  BaseInfoBaseImpl::s_init_list->push_back (elem);
+
+  if (BaseInfoBaseImpl::s_bi_by_ti) {
+    BaseInfoBaseImpl::bi_by_ti_map_type::iterator i = 
+      BaseInfoBaseImpl::s_bi_by_ti->find (tinfo);
+    if (i != BaseInfoBaseImpl::s_bi_by_ti->end() && 
+        !i->second->m_impl->m_needs_init)
+      i->second->m_impl->m_needs_init = true;
+  }
+}
+
+
+/**
+ * @brief Run initializations for this class, if needed.
+ */
+void BaseInfoBase::maybeInit()
+{
+  if (m_impl->m_needs_init)
+    find (*m_impl->m_typeinfo);
+}
+
+
+
+/**
+ * @brief Try to translate a type_info to a CLID by looking in the initlist.
+ * @param tinfo The type to translate.
+ * @returns The corresponding CLID, or CLID_NULL.
+ */
+CLID BaseInfoBase::clid_from_initlist (const std::type_info& tinfo)
+{
+  if (!BaseInfoBaseImpl::s_init_list) return CLID_NULL;
+  size_t sz = BaseInfoBaseImpl::s_init_list->size();
+  for (size_t i = 0; i < sz; i++) {
+    const BaseInfoBaseImpl::init_elem_t& elt =
+      (*BaseInfoBaseImpl::s_init_list)[i];
+    if (elt.m_ti == &tinfo)
+      return elt.m_clid;
+  }
+  return CLID_NULL;
+}
+
+
+/// Declare the static members of @c BaseInfoBaseImpl.
+BaseInfoBaseImpl::bi_by_clid_map_type*      BaseInfoBaseImpl::s_bi_by_clid = 0;
+BaseInfoBaseImpl::bi_by_ti_map_type*        BaseInfoBaseImpl::s_bi_by_ti = 0;
+std::vector<BaseInfoBaseImpl::init_elem_t>* BaseInfoBaseImpl::s_init_list = 0;
+//boost::mutex                                BaseInfoBaseImpl::s_mutex;
+
+// To get them deleted.
+BaseInfoBaseImpl::Deleter BaseInfoBaseImpl::s_deleter;
+BaseInfoBaseImpl::Deleter::~Deleter()
+{
+  delete s_bi_by_clid;
+  delete s_bi_by_ti;
+  delete s_init_list;
+}
+
+} // namespace SG
diff --git a/Control/SGTools/src/CLIDRegistry.cxx b/Control/SGTools/src/CLIDRegistry.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..a21906f1e425e96ec55a2f8ab849b36ebabf6793
--- /dev/null
+++ b/Control/SGTools/src/CLIDRegistry.cxx
@@ -0,0 +1,60 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "SGTools/CLIDRegistry.h"
+/* #include <algorithm> */
+using namespace std;
+
+const unsigned long CLIDRegistry::MINCLID = detail::MINCLID;
+const unsigned long CLIDRegistry::MAXCLID = detail::MAXCLID;
+unsigned int _alreadyDone (0);
+
+
+//   bool 
+//   CLIDRegistry::addEntry(unsigned long id, const string& typeName) {
+//     assert( MINCLID <= id && id <= MAXCLID );
+//     registry().push_back(pair<unsigned long, string>(id,typeName));
+//     return true;
+//   }
+
+
+CLIDRegistry::const_iterator CLIDRegistry::begin() {
+#ifdef CLIDREG_DEBUG
+  cerr << "CLIDRegistry::begin: returns " 
+	    << &*(registry().begin()) << " for registry " <<&registry() 
+	    <<endl;
+#endif	
+  return registry().begin();
+}
+
+
+CLIDRegistry::const_iterator CLIDRegistry::end() {
+#ifdef CLIDREG_DEBUG
+  cerr << "CLIDRegistry::end: returns " 
+	    << &*(registry().end()) << " for registry " <<&registry() 
+	    <<endl;
+#endif	
+  return registry().end();
+  //return unique(registry().begin(), registry().end());  //FIXME O(N)!
+}
+
+bool
+CLIDRegistry::hasNewEntries() {
+  return (_alreadyDone < CLIDRegistry::registry().size());
+}
+
+std::pair<CLIDRegistry::const_iterator, CLIDRegistry::const_iterator> 
+CLIDRegistry::newEntries() {
+  std::pair<CLIDRegistry::const_iterator, CLIDRegistry::const_iterator> ret =
+     std::make_pair(CLIDRegistry::begin()+_alreadyDone, 
+                    CLIDRegistry::end());
+  _alreadyDone = CLIDRegistry::registry().size();
+  return ret;
+}
+
+
+CLIDRegistry::CLIDRegistryImpl& CLIDRegistry::registry() {
+  static CLIDRegistryImpl _reg;
+  return _reg;
+}
diff --git a/Control/SGTools/src/DataHandleBase.cxx b/Control/SGTools/src/DataHandleBase.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e6e03b6ebf0f9f2f6a8382d289010f1eac7c009f
--- /dev/null
+++ b/Control/SGTools/src/DataHandleBase.cxx
@@ -0,0 +1,249 @@
+///////////////////////// -*- C++ -*- /////////////////////////////
+
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// DataHandleBase.cxx 
+// Implementation file for class DataHandleBase
+// Author: S.Binet<binet@cern.ch>
+/////////////////////////////////////////////////////////////////// 
+
+// SGTools includes
+#include "SGTools/DataHandleBase.h"
+
+// STL includes
+
+
+
+/////////////////////////////////////////////////////////////////// 
+// Public methods: 
+/////////////////////////////////////////////////////////////////// 
+
+// Constructors
+////////////////
+
+/// Default constructor: 
+DataHandleBase::DataHandleBase() :
+  IResetable(),
+  m_itr(), 
+  m_itrEnd(), 
+  m_proxy(0),
+  //m_ptr(0),
+  m_useItr(false)
+{}
+
+/// Copy constructor: 
+DataHandleBase::DataHandleBase( const DataHandleBase& rhs ) :
+  IResetable(),
+  m_itr(rhs.m_itr), 
+  m_itrEnd(rhs.m_itrEnd),
+  m_proxy(rhs.m_proxy), 
+  //m_ptr(rhs.m_ptr),
+  m_useItr(rhs.m_useItr)
+{
+  if (m_proxy) {
+    m_proxy->addRef();
+  }
+}
+
+
+/// Assignment operator: 
+DataHandleBase& 
+DataHandleBase::operator=( const DataHandleBase& rhs )
+{
+  if (this != &rhs) {
+    if (m_proxy) {
+      m_proxy->release();
+    }
+
+    m_itr =    rhs.m_itr;
+    m_itrEnd = rhs.m_itrEnd;
+    m_useItr = rhs.m_useItr;
+    m_proxy =  rhs.m_proxy;
+    //m_ptr =    rhs.m_ptr;
+    if (m_proxy) {
+      m_proxy->addRef();
+    }
+  }
+
+  return *this;
+}
+
+/// Constructor with parameters: 
+DataHandleBase::DataHandleBase(SG::DataProxy* proxy) :
+  IResetable(),
+  m_itr(), 
+  m_itrEnd(), 
+  m_proxy(proxy), 
+  //m_ptr(0),
+  m_useItr(false)
+{
+  if (m_proxy) {
+    m_proxy->addRef();
+  }
+}
+
+DataHandleBase::DataHandleBase(const SG::ConstProxyIterator& itr,
+                               const SG::ConstProxyIterator& itrEnd) :
+  IResetable(),
+  m_itr(itr), 
+  m_itrEnd(itrEnd),
+  m_proxy(0), 
+  //m_ptr(0),
+  m_useItr(true)
+{
+  if (m_itr != m_itrEnd) {
+    m_proxy = m_itr->second;
+  }
+
+  if (m_proxy) {
+    m_proxy->addRef();
+  }
+}
+
+
+/// Destructor: 
+DataHandleBase::~DataHandleBase()
+{
+  if (m_proxy != 0) {
+    m_proxy->unbindHandle(this);
+    m_proxy->release();
+  }
+}
+
+// Destructor
+///////////////
+
+/////////////////////////////////////////////////////////////////// 
+// Const methods: 
+///////////////////////////////////////////////////////////////////
+
+StatusCode 
+DataHandleBase::setState(SG::ConstProxyIterator &itr, 
+                         const SG::ConstProxyIterator &itrEnd) const 
+{
+  if (m_proxy) m_proxy->release();
+
+  m_itr = itr;
+  m_itrEnd = itrEnd;
+  m_useItr = true;
+
+  // ouch! FIXME ?
+  // we could have a void* m_ptr data member and have a
+  // typeless_dataPointer method using the typeless machinery of
+  // DataProxy+DataBucketBase...
+  const_cast<DataHandleBase*>(this)->reset();
+
+  // scan from itr to itrEnd and set m_itr to the first valid iterator:
+
+  for (; itr != itrEnd; itr++) {
+    if (itr->second->isValid()) {
+      m_itr = itr;
+      m_proxy = m_itr->second;
+      if (m_proxy) m_proxy->addRef();
+      return StatusCode::SUCCESS;
+    }
+  }
+
+  m_itr = itrEnd;
+  m_proxy = 0;
+  
+  return StatusCode::FAILURE; 
+}
+
+StatusCode 
+DataHandleBase::setState(SG::DataProxy* proxy) const
+{
+  if (0 == proxy || !proxy->isValid()) {
+    return StatusCode::FAILURE;
+  }
+
+  if (m_proxy != proxy) {
+    if (m_proxy) m_proxy->release();
+    m_proxy = proxy;
+    m_proxy->addRef();
+  }
+
+  m_useItr = false;
+  const_cast<DataHandleBase*>(this)->reset();
+
+  return StatusCode::SUCCESS;
+}
+
+StatusCode 
+DataHandleBase::setState(IProxyDict* store, const ID_type& key) const 
+{
+  if (0 == store) {
+    return StatusCode::FAILURE;
+  }
+  CLID cid = this->clid();
+  SG::DataProxy* proxy = store->proxy(cid, key);
+  return this->setState(proxy);
+}
+
+const std::string& 
+DataHandleBase::key() const
+{
+  if (m_itr == m_itrEnd) {
+    return m_proxy->name();
+  } else {
+    return m_itr->first;
+  }
+}
+
+bool 
+DataHandleBase::isConst() const
+{
+  return 0 != m_proxy 
+    ? m_proxy->isConst() 
+    : false;
+}
+
+
+// A weaker test that
+// *does not* retrieve the GaudiObject to check validity if not already done
+bool 
+DataHandleBase::isInitialized() const
+{
+  return (0 != m_proxy);
+}
+
+/////////////////////////////////////////////////////////////////// 
+// Non-const methods: 
+/////////////////////////////////////////////////////////////////// 
+
+StatusCode 
+DataHandleBase::setState(SG::DataProxy* proxy)
+{
+  if (0 == proxy || !proxy->isValid() || proxy->isConst()) {
+    return StatusCode::FAILURE;
+  }
+
+  if (m_proxy != proxy) {
+    if (m_proxy) m_proxy->release();
+    m_proxy = proxy;
+    m_proxy->addRef();
+  }
+
+  m_useItr = false;
+  this->reset();
+  return StatusCode::SUCCESS;
+}
+
+StatusCode 
+DataHandleBase::setState(IProxyDict* store, const ID_type& key)
+{
+  if (0 == store) {
+    return StatusCode::FAILURE;
+  }
+  CLID cid = this->clid();
+  SG::DataProxy* proxy = store->proxy(cid, key);
+  return this->setState(proxy);
+}
+
+/////////////////////////////////////////////////////////////////// 
+// Protected methods: 
+/////////////////////////////////////////////////////////////////// 
+
+
diff --git a/Control/SGTools/src/DataProxy.cxx b/Control/SGTools/src/DataProxy.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..a442d71accd5d6f6fc5b728db52b385ebb8b0ab6
--- /dev/null
+++ b/Control/SGTools/src/DataProxy.cxx
@@ -0,0 +1,345 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include <cassert>
+
+#include "AthenaKernel/IResetable.h"
+#include "AthenaKernel/getMessageSvc.h"
+#include "GaudiKernel/MsgStream.h"
+
+#include "GaudiKernel/DataObject.h"
+#include "GaudiKernel/IConversionSvc.h"
+#include "GaudiKernel/GenericAddress.h"
+#include "SGTools/TransientAddress.h"
+#include "SGTools/T2pMap.h"
+#include "SGTools/DataBucketBase.h"
+#include <stdexcept>
+using SG::TransientAddress;
+
+
+#include "SGTools/DataProxy.h"
+using SG::DataProxy;
+
+
+namespace {
+  ///sets pMember to pgref (resetting it if pgref is 0). Handles Gaudi refcount
+  template <class GAUDIREF>
+  void setGaudiRef(GAUDIREF* pgref, GAUDIREF*& pMember) {
+    if (0 != pgref) pgref->addRef();
+    if (0 != pMember) pMember->release();
+    pMember = pgref;
+  }
+  
+  ///resets pMember. Handles Gaudi refcount
+  template <class GAUDIREF>
+  void resetGaudiRef(GAUDIREF*& pMember) { setGaudiRef((GAUDIREF*)0, pMember); }
+  
+} //end of unnamed namespace
+
+// Default Constructor
+DataProxy::DataProxy():
+  m_tAddress(new TransientAddress()),
+  m_refCount(0),
+  m_dObject(0), 
+  m_dataLoader(0),
+  m_const(false),
+  m_origConst(false),
+  m_storageType(0),
+  m_resetFlag(true),
+  m_t2p(0),
+  m_errno(ALLOK),
+  m_store(0)
+{ 
+}
+
+// DataProxy constructor with Transient Address
+// (typically called from Proxy Provider)
+DataProxy::DataProxy(TransientAddress* tAddr, 
+		     IConversionSvc* svc,
+		     bool constFlag, bool resetOnly):
+  m_tAddress(tAddr),
+  m_refCount(0),
+  m_dObject(0), 
+  m_dataLoader(svc),
+  m_const(constFlag),
+  m_origConst(constFlag),
+  m_storageType(0),
+  m_resetFlag(resetOnly),
+  m_t2p(0),
+  m_errno(ALLOK),
+  m_store(0)
+{
+  //assert( tAddr->clID() != 0 );
+  if (svc) svc->addRef();
+}
+
+// with Data Object:
+// (typically called from a StoreGate record
+DataProxy::DataProxy(DataObject* dObject, 
+		     TransientAddress* tAddr,
+		     bool constFlag, bool resetOnly):
+  m_tAddress(tAddr),
+  m_refCount(0),
+  m_dObject(0), 
+  m_dataLoader(0),
+  m_const(constFlag),
+  m_origConst(constFlag),
+  m_storageType(0),
+  m_resetFlag(resetOnly),
+  m_t2p(0),
+  m_errno(ALLOK),
+  m_store(0)
+{
+  setObject(dObject);
+}
+
+// Destructor
+DataProxy::~DataProxy()
+{  
+  resetGaudiRef(m_dataLoader);
+  resetGaudiRef(m_dObject);
+  delete m_tAddress;
+}
+
+void DataProxy::setT2p(T2pMap* t2p)
+{
+  m_t2p = t2p;
+}
+
+
+/**
+ * @brief Mark this object as const.  (Lock the object.)
+ *
+ * If the object held that derives from @c ILockable, then we also
+ * call @c lock on the object.
+ */
+void DataProxy::setConst()
+{
+  m_const = true;
+  lock();
+}
+
+bool DataProxy::bindHandle(IResetable* ir) {
+  if (ir->isSet()) {
+    return false;
+  } else {
+    m_handles.push_back(ir); 
+    return true;
+  }
+}
+
+
+
+void DataProxy::reset()
+{
+
+  if (! m_handles.empty()) { resetBoundHandles(); }
+
+  resetGaudiRef(m_dObject);
+  m_tAddress->reset();
+  m_const = m_origConst;
+
+}
+
+/// don't need a comment
+void DataProxy::resetBoundHandles() {
+  std::list<IResetable*>::iterator itre=m_handles.end();
+  for (std::list<IResetable*>::iterator itr=m_handles.begin();
+       itr != itre; ++itr) {
+    (*itr)->reset();
+  }
+}
+
+void DataProxy::unbindHandle(IResetable *ir) {
+  if( m_handles.empty() ) { return; }
+  m_handles.remove( ir );
+}
+  
+/// return refCount
+unsigned long DataProxy::refCount() const
+{
+  return m_refCount;
+}
+
+/// Add reference to object
+unsigned long DataProxy::addRef()
+{ 
+  return ++m_refCount;
+}
+
+/// release reference to object
+unsigned long DataProxy::release()
+{ 
+  unsigned long count(--m_refCount);
+  if ( 0 == count ) delete this;
+  return count;
+}
+
+
+///request to release the instance (may just reset it)
+bool DataProxy::requestRelease(bool force /*= false*/) {
+  bool canRelease = !isResetOnly() || force;
+#ifndef NDEBUG
+  MsgStream gLog(m_ims, "DataProxy");
+  if (gLog.level() <= MSG::VERBOSE) {
+    gLog << MSG::VERBOSE << "requestRelease(): "
+	 << (canRelease ? " release " : " reset")
+	 <<" object " 
+	 << name() << " CLID " << clID() << " address " << MSG::hex
+	 << object() << MSG::dec << endreq;
+  }
+#endif
+  if (canRelease)  release();
+    else             reset();
+  return canRelease;
+}
+
+/// set a DataObject address
+void DataProxy::setObject(DataObject* dObject)
+{
+  setGaudiRef(dObject, m_dObject);
+  if (0 != m_dObject) {
+    m_dObject->setRegistry(this);
+    if (m_const) lock();
+  }
+}
+
+
+// set IOpaqueAddress
+void DataProxy::setAddress(IOpaqueAddress* address)
+{
+  m_tAddress->setAddress(address);
+}
+//////////////////////////////////////////////////////////////
+
+/// Access DataObject on-demand using conversion service
+DataObject* DataProxy::accessData()
+{
+  if (0 != m_dObject) return m_dObject;  // cached object
+
+  if (0 == m_dataLoader) {
+    //MsgStream gLog(m_ims, "DataProxy");
+    //gLog << MSG::WARNING
+    //	  << "accessData:  IConversionSvc ptr not set" <<endreq;
+    m_errno=NOCNVSVC;
+    setObject(0);
+    return 0;   
+  }
+  if (!isValidAddress()) {
+    MsgStream gLog(m_ims, "DataProxy");
+    gLog << MSG::WARNING
+	 << "accessData:  IOA pointer not set" <<endreq;
+    m_errno=NOIOA;
+    setObject(0);
+    return 0;
+  }
+
+  DataObject* obj(0);
+  StatusCode sc = m_dataLoader->createObj(m_tAddress->address(), obj);
+
+  if ( sc.isSuccess() )
+  {  
+    setObject(obj);
+    DataBucketBase* bucket = dynamic_cast<DataBucketBase*>(obj);
+    if (bucket) {
+      void* payload = bucket->object();
+      m_t2p->t2pRegister(payload, this);
+      m_errno=ALLOK;
+
+  
+      // Register bases as well.
+      const SG::BaseInfoBase* bi = SG::BaseInfoBase::find (m_tAddress->clID());
+      if (bi) {
+        std::vector<CLID> base_clids = bi->get_bases();
+        for (unsigned i=0; i < base_clids.size(); i++) {
+          void* bobj = SG::DataProxy_cast (this, base_clids[i]);
+          if (bobj && bobj != payload)
+            m_t2p->t2pRegister (bobj, this);
+        }
+      }
+    } else {
+      MsgStream gLog(m_ims, "DataProxy");
+      gLog << MSG::ERROR
+	   << "accessData: ERROR registering object in t2p map" 
+	   <<m_tAddress->clID() << '/' << m_tAddress->name() << '\n'
+	   <<" Returning NULL DataObject pointer  " << endreq;
+      obj=0; 
+      setObject(0);
+      m_errno=T2PREGFAILED;
+      }
+  } else {
+    MsgStream gLog(m_ims, "DataProxy");
+    gLog << MSG::WARNING 
+	 << "accessData: conversion failed for data object " 
+	 <<m_tAddress->clID() << '/' << m_tAddress->name() << '\n'
+	 <<" Returning NULL DataObject pointer  " << endreq;
+    obj=0; 
+    setObject(0);
+    m_errno=CNVFAILED;
+  }
+
+  return obj;
+
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+bool DataProxy::isValidAddress() const
+{
+  return (0 != m_tAddress && m_tAddress->isValid());
+}
+
+bool DataProxy::isValidObject() const
+{
+  // FIXME: should we try to chase?
+  return (0!= m_dObject);
+}
+  
+bool DataProxy::isValid() const
+{
+  return (isValidObject() || isValidAddress());
+}
+
+
+/**
+ * @brief Try to get the pointer back from a @a DataProxy,
+ *        converted to be of type @a clid.
+ * @param proxy The @a DataProxy.
+ * @param clid The ID of the class to which to convert.
+ *
+ * Only works if the held object is a @a DataBucket.
+ * Returns 0 on failure,
+ */
+void* SG::DataProxy_cast (SG::DataProxy* proxy, CLID clid)
+{
+  if (0 == proxy || !proxy->isValid())
+    return 0;
+  DataObject* pObject = proxy->accessData();
+  if (0 == pObject)
+    return 0;
+  return SG::Storable_cast (pObject, clid, proxy, proxy->isConst());
+}
+
+  
+/**
+ * @brief Register a transient object in a t2p map.
+ * @param trans The object to register.
+ */
+void DataProxy::registerTransient (void* p)
+{
+  if (m_t2p)
+    m_t2p->t2pRegister (p, this);
+}
+
+
+/**
+ * @brief Lock the data object we're holding, if any.
+ */
+void DataProxy::lock()
+{
+  DataBucketBase* bucket = dynamic_cast<DataBucketBase*>(m_dObject);
+  if (bucket)
+    bucket->lock();
+}
+
diff --git a/Control/SGTools/src/DataStore.cxx b/Control/SGTools/src/DataStore.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..035762c7654bceb22004dbb384158a463867dd42
--- /dev/null
+++ b/Control/SGTools/src/DataStore.cxx
@@ -0,0 +1,493 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "SGTools/DataStore.h"
+#include "SGTools/DataProxy.h"
+#include "SGTools/IStringPool.h"
+#include "SGTools/exceptions.h"
+#include "GaudiKernel/ClassID.h"
+#include "GaudiKernel/MsgStream.h"
+#include "GaudiKernel/Bootstrap.h"
+#include "GaudiKernel/ISvcLocator.h"
+#include "SGAudCore/ISGAudSvc.h"
+
+using namespace std;
+using SG::DataStore;
+using SG::DataProxy;
+using SG::ProxyMap;
+using SG::ProxyIterator;
+using SG::ConstProxyIterator;
+
+
+/**
+ * @brief Constructor.
+ * @param pool The string pool associated with this store.
+ */
+DataStore::DataStore (IProxyDictWithPool& pool)
+  : m_pool (pool),
+    m_storeMap(), m_storeID(StoreID::UNKNOWN), m_t2p(), 
+    m_pSGAudSvc(0), m_noAudSvc(0), m_pSvcLoc(0)
+{
+   setSvcLoc().ignore();
+}
+
+//Destructor
+DataStore::~DataStore()
+{
+  clearStore();
+}
+
+StatusCode DataStore::setSvcLoc(){
+  StatusCode sc(StatusCode::FAILURE);
+  m_pSvcLoc = Gaudi::svcLocator( );
+  if (!m_pSvcLoc) std::cout<<"DataStore::setSvcLoc: WARNING svcLocator not found! "<<std::endl;
+  return sc;
+}
+
+void DataStore::setSGAudSvc() const { //m_noAudSvc and m_pSGAudSvc are mutable 
+  if (0 == m_pSGAudSvc) {
+    //try once to get the service
+    const bool DONOTCREATE(false);
+    if (!m_noAudSvc) {
+      m_noAudSvc = m_pSvcLoc->service("SGAudSvc", m_pSGAudSvc, 
+				      DONOTCREATE).isFailure();
+    }
+  }
+  return;
+}
+
+
+//////////////////////////////////////////////////////////////
+void DataStore::clearStore(bool force /*= false*/, MsgStream* pmlog/*=0*/)
+{
+
+  StoreIterator s_iter = m_storeMap.begin();
+  StoreIterator s_end  = m_storeMap.end();
+
+  for (; s_iter != s_end; s_iter++) 
+  {
+
+    ProxyMap& pmap = s_iter->second;
+
+    ProxyIterator iter = pmap.begin();
+    ProxyIterator end   = pmap.end();
+
+    while (iter != end) {
+
+      if (pmlog) {
+	*pmlog << MSG::VERBOSE 
+	       << "DataStore::clearStore() " 
+	       << (force ? "forcing" : "requesting")
+	       << " release of DataProxy @" << iter->second
+	       << ", recorded with key=" << iter->second->name() 
+	       << ", CLID=" << iter->second->clID()
+	       << ", containing data object @" << iter->second->object();
+	pmlog->flush(); //make sure this is printed now
+      }
+      if (iter->second->requestRelease(force)) { //request proxy deletion
+	//proxy was released, remove map entry
+        sgkey_t sgkey = m_pool.stringToKey (iter->first, s_iter->first);
+        m_keyMap.erase (sgkey);
+        
+	pmap.erase(iter++);  //increment the pre-erase iterator (Effective STL Item 9)
+      } else {
+	//proxy was reset, keep map entry
+	++iter;
+      }
+      if(pmlog) *pmlog << MSG::VERBOSE << "  ... -> DONE" << endmsg;
+    }
+  }
+
+  // clear T2PMap
+  m_t2p.clear();
+}
+
+/////////////////////////////////////////////////////////////
+// access all the keys associated with an object: 
+// 
+void DataStore::keys(const CLID& id, std::vector<std::string>& vkeys,
+		     bool includeAlias, bool onlyValid)
+{
+  vector<string> tkeys;
+  ProxyMap& pmap = m_storeMap[id];
+  ConstProxyIterator p_iter = pmap.begin();
+  for (; p_iter != pmap.end(); p_iter++) {
+    bool includeProxy(true);
+    if (onlyValid) includeProxy=p_iter->second->isValid();
+    if (includeAlias) {
+      if (includeProxy) tkeys.push_back(p_iter->first);
+    }
+    else {
+      if (p_iter->first == p_iter->second->name() && includeProxy) 
+	tkeys.push_back(p_iter->first);
+    }
+  }
+  vkeys.swap(tkeys);
+  return;
+}
+
+//////////////////////////////////////////////////////////////
+//---------------------------------------------------------------//
+// record the proxy in StoreGate
+StatusCode 
+DataStore::addToStore(const CLID& id, DataProxy* dp)
+{
+  StatusCode sc(StatusCode::FAILURE);
+  if (0 != dp) {
+    TransientAddress* tad = dp->transientAddress();
+
+    if (id == 0 && tad->clID() == 0 && tad->sgkey() != 0) {
+      // Handle a dummied proxy.
+      m_keyMap[tad->sgkey()] = dp;
+    }
+    else {
+      ProxyMap& pmap = m_storeMap[id];
+
+      // Set the primary key.
+      sgkey_t primary_sgkey = m_pool.stringToKey (tad->name(), tad->clID());
+      tad->setSGKey (primary_sgkey);
+
+      pmap.insert(ProxyMap::value_type(dp->name(), dp));
+
+      sgkey_t sgkey = primary_sgkey;
+      if (id != tad->clID())
+        sgkey = m_pool.stringToKey (tad->name(), id);
+      m_keyMap[sgkey] = dp;
+    }
+
+    // Note : No checking if proxy already exists in store because it
+    // is already checked in StoreGateSvc.  
+    //  if (pmap.find(dp->name()) == pmap.end()) {
+    dp->addRef();   // The store now owns this
+    dp->setT2p(&m_t2p);
+    dp->setStore(&m_pool);
+
+    sc =  StatusCode::SUCCESS;
+    //  } else {
+    //    std::cout << "!!!!!!!!!!!! Dupe found in store " << this << "CLID/KEY" << id << "/" << dp->name() << std::endl;
+    //  }
+  }
+  return sc;
+
+}
+ 
+//////////////////////////////////////////////////////////////////
+//---------------------------------------------------------------//
+// if Proxy is a resettable proxy only then reset it, otherwise
+// delete it and remove from proxy map.
+StatusCode
+DataStore::removeProxy(DataProxy* proxy, bool forceRemove)
+{
+  StatusCode sc(StatusCode::FAILURE);
+  if (0 == proxy) return sc;
+
+  if (!forceRemove && proxy->isResetOnly()) {
+    proxy->reset();
+    sc =  StatusCode::SUCCESS;
+  } else {
+    
+    SG::DataProxy::CLIDCont_t clids = proxy->transientID();
+    std::string name = proxy->name();
+    sgkey_t primary_sgkey = proxy->transientAddress()->sgkey();
+
+    StoreIterator storeIter = m_storeMap.find(proxy->clID());
+    if (storeIter != m_storeMap.end()) {
+      CLID clid = proxy->clID();
+      // first remove the alias key:
+      ProxyMap& pmap = m_storeMap[clid];
+      SG::DataProxy::AliasCont_t alias_set = proxy->alias();
+      for (SG::DataProxy::AliasCont_t::const_iterator i = alias_set.begin();
+	   i != alias_set.end(); ++i)
+      {
+        m_keyMap.erase (m_pool.stringToKey (*i, clid));
+	if (1 == pmap.erase(*i)) proxy->release();
+      }
+      
+      // then remove the primary key
+      m_keyMap.erase (primary_sgkey);
+      if (1 == storeIter->second.erase(name)) {
+	proxy->release();
+	sc = StatusCode::SUCCESS;
+      }
+
+      // Remove all symlinks too.
+      for (SG::DataProxy::CLIDCont_t::const_iterator i = clids.begin();
+	   i != clids.end(); ++i)
+      {
+	storeIter = m_storeMap.find(*i);
+	if (storeIter != m_storeMap.end()) {
+          m_keyMap.erase (m_pool.stringToKey (name, *i));
+	  if (1 == storeIter->second.erase(name))
+	    proxy->release();
+	}
+      } //symlinks loop
+    } //proxy there
+  } //reset only
+  return sc;
+}
+
+//////////////////////////////////////////////////////////////
+//---------------------------------------------------------------//
+// record the symlink in StoreGate
+StatusCode 
+DataStore::addSymLink(const CLID& linkid, DataProxy* dp)
+{
+  // Make sure the symlink doesn't already exist.
+  DataProxy* exist = proxy_exact (linkid, dp->name());
+  if (exist == dp) {
+    // Entry already exists pointing at the desired proxy.
+    return StatusCode::SUCCESS;
+  }
+  else if (exist != 0) {
+    // Entry already exists pointing at another proxy.
+    // Don't change the existing entry.
+    return StatusCode::FAILURE;
+  }
+
+  dp->transientAddress()->setTransientID(linkid); 
+  return addToStore(linkid, dp);
+}
+//---------------------------------------------------------------//
+// record the alias in StoreGate
+StatusCode
+DataStore::addAlias(const std::string& aliasKey, DataProxy* dp)
+{
+  // locate proxy map and add alias to proxymap
+  ProxyMap& pmap = m_storeMap[dp->clID()];
+
+  // check if another proxy for the same type caries the same alias.
+  // if yes, then remove that alias from that proxy and establish the
+  // alias in the new proxy.
+  // pmap.insert will overwrite, associate alias with new proxy.
+  ConstProxyIterator p_iter = pmap.find(aliasKey);
+  if (p_iter != pmap.end() && dp->clID() == p_iter->second->clID()) {
+    if (dp->name() == p_iter->second->name()) return StatusCode::SUCCESS;
+    p_iter->second->transientAddress()->removeAlias(aliasKey);
+    p_iter->second->release();
+  }
+  // set alias in proxy
+  dp->transientAddress()->setAlias(aliasKey);
+  dp->addRef();
+  pmap[aliasKey] = dp;
+  m_keyMap[m_pool.stringToKey (aliasKey, dp->clID())] = dp;
+  //  pmap.insert(ProxyMap::value_type(aliasKey, dp));
+  // use [] as it overwrites, .insert ignores second entry
+
+  return StatusCode::SUCCESS;
+}
+//---------------------------------------------------------------//
+// Count instances of TYPE in store
+int DataStore::typeCount(const CLID& id) const
+{
+  ConstStoreIterator storeIter = m_storeMap.find(id);
+  if (storeIter == m_storeMap.end()) return 0;
+  return (storeIter->second).size();
+}
+
+//---------------------------------------------------------------//
+// Return proxy for a given Transient Address
+DataProxy* DataStore::proxy(const TransientAddress* tAddr) const
+{
+  return proxy(tAddr->clID(), tAddr->name());
+}
+
+// Return proxy for a given Transient ID (TYPE and KEY) 
+DataProxy* DataStore::proxy(const CLID& id, const std::string& key) const
+{	 
+
+  // The logic here: if a key is specified, we locate it.
+  // If we don't find it and the default key (DEFAULTKEY) is specified,
+  // then we return any existing proxy for this type as long as there
+  // is exactly one, not counting aliases.  More than one would be ambiguous
+	  
+  ConstStoreIterator s_iter = m_storeMap.find(id);
+  DataProxy *p(0);
+  if (s_iter != m_storeMap.end()) 
+  {
+    const ProxyMap& pmap = s_iter->second;
+    ConstProxyIterator p_iter = pmap.find(key);
+    if (p_iter != pmap.end()) {
+      p=p_iter->second;
+
+    } else if (key == SG::DEFAULTKEY && !pmap.empty()) {
+      // we did not find the object using key.
+      // Now check for default object.
+      // Simple case first --- single object.
+      if (pmap.size() == 1) {
+        p = pmap.begin()->second;
+      } else {
+        // Otherwise, match only the exact type requested.
+        ConstProxyIterator p_match = pmap.end();
+        size_t nmatch = 0;
+        for (p_iter = pmap.begin(); p_iter != pmap.end(); ++p_iter) {
+          if (p_iter->second->transientAddress()->clID() == id) {
+            ++nmatch;
+            if (p_match == pmap.end()) p_match = p_iter;
+          }
+        }
+
+        // We must have matched only one object, not counting its aliases.
+        // Notice: we test that there are less than two matches: symlinked objects
+        // may carry aliases from the concrete class. In that case nmatch
+        // may be equal to or even smaller than the number of aliases
+        if (nmatch > 0 &&
+            (int(nmatch - p_match->second->alias().size()) < 2))
+        {
+          p = pmap.begin()->second;
+        }
+      }
+    }
+    else {
+      p = const_cast<DataStore*>(this)->findDummy (id, key);
+    }
+  }
+  else {
+    p = const_cast<DataStore*>(this)->findDummy (id, key);
+  }
+
+  if (p && doAudit()) 
+    m_pSGAudSvc->SGAudit(p->transientAddress()->name(), id, 0, m_storeID);
+
+  return p;
+}
+
+
+/**
+ * @brief Look for (and convert) a matching dummy proxy.
+ * @param id The CLID for which to search.
+ * @param key The key for which to search.
+ *
+ * In some cases, we may enter into the store a `dummy' proxy,
+ * which is identified only by the hashed CLID/key pair.
+ * (This can happen when we have a link to an object that's not
+ * listed in the DataHeader; in this case, we know the only hashed key
+ * and not the CLID or key.)
+ *
+ * This function is called after we fail to find a proxy by CLID/key.
+ * It additionally checks to see if there exists a dummy proxy with
+ * a hash matching this CLID/key.  If so, the CLID/key are filled
+ * in in the proxy, and the proxy is entered in m_storeMap.
+ *
+ * Returns either the matching proxy or 0.
+ */
+DataProxy* DataStore::findDummy (CLID id, const std::string& key)
+{
+  sgkey_t sgkey = m_pool.stringToKey (key, id);
+  DataProxy* p = proxy_exact (sgkey);
+  if (p) {
+    p->transientAddress()->setID (id, key);
+    ProxyMap& pmap = m_storeMap[id];
+    if (!pmap.insert(ProxyMap::value_type(key, p)).second) {
+      // This shouldn't happen.
+      DataProxy* p2 = pmap[key];
+      throw SG::ExcProxyCollision (id, key, p2->clID(), p2->name());
+    }
+  }
+  return p;
+}
+
+
+/// get proxy with given key. Returns 0 to flag failure
+/// the key must match exactly (no wild carding for the default key)
+DataProxy* DataStore::proxy_exact(sgkey_t sgkey) const
+{
+  if (doAudit()) {
+    CLID clid;
+    const std::string* strkey = m_pool.keyToString (sgkey, clid);
+    if (strkey)
+      m_pSGAudSvc->SGAudit(*strkey, clid, 0, m_storeID);
+  }
+  KeyMap_t::const_iterator i = m_keyMap.find (sgkey);
+  if (i != m_keyMap.end())
+    return i->second;
+  return 0;
+}
+
+
+/// get proxy with given key. Returns 0 to flag failure
+/// the key must match exactly (no wild carding for the default key)
+DataProxy* DataStore::proxy_exact(const CLID& id,
+                                  const std::string& key) const
+{
+  return proxy_exact (m_pool.stringToKey (key, id));
+}
+
+
+//---------------------------------------------------------------//
+// Return an iterator over proxies for a given CLID:
+StatusCode DataStore::pRange(const CLID& id, ConstProxyIterator& pf,
+			                     ConstProxyIterator& pe) const
+{
+  static const ProxyMap emptyMap;
+  StatusCode sc(StatusCode::FAILURE);
+
+  ConstStoreIterator storeIter = m_storeMap.find(id);
+  if (storeIter != m_storeMap.end()) 
+  {
+    const ProxyMap& pmap = storeIter->second;
+    pf = pmap.begin();
+    pe = pmap.end();
+    if (pmap.size() > 0) sc = StatusCode::SUCCESS;
+  } else {
+    //keep valgrind happy
+    pf = emptyMap.end();
+    pe = emptyMap.end();
+  }
+  return sc;
+}
+//---------------------------------------------------------------//
+// Return an iterator over the Store Map
+StatusCode DataStore::tRange(ConstStoreIterator& tf,
+			     ConstStoreIterator& te) const
+{
+  tf = m_storeMap.begin();
+  te = m_storeMap.end();
+  return StatusCode::SUCCESS;
+}
+//---------------------------------------------------------------//
+// Build a list of proxies that are in the Store:
+StatusCode DataStore::proxyList(std::list<DataProxy*>& plist) const
+{
+  ConstProxyIterator pf, pe;
+  ConstStoreIterator sf, se;
+  (tRange(sf, se)).ignore();
+  for (; sf!=se; sf++) 
+  {
+    (pRange(sf->first, pf, pe)).ignore();
+    for (; pf!=pe; pf++) {
+      // FIXME : Check validity of proxy.
+      plist.push_back(pf->second);
+    }
+  }
+  return StatusCode::SUCCESS;
+}
+//---------------------------------------------------------------//
+// locate Persistent Representation of a Transient Object
+//
+DataProxy* DataStore::locatePersistent(const void* const pTransient) const
+{
+  return m_t2p.locatePersistent(pTransient);
+}
+
+//////////////////////////////////////////////////////////////////
+StatusCode
+DataStore::t2pRegister(const void* const pTrans, DataProxy* const pPers)
+{
+    std::string name=pPers->name();
+    int i=name.find("/", 0);
+    name=name.erase(0,i+1);  
+
+  if (doAudit()) m_pSGAudSvc->SGAudit(name, pPers->clID(), 1, m_storeID);
+
+  return (m_t2p.t2pRegister(pTrans, pPers)) ? 
+			StatusCode::SUCCESS :
+			StatusCode::FAILURE; 
+}
+
+
+
+
+
+
+
diff --git a/Control/SGTools/src/IProxyDictWithPool.cxx b/Control/SGTools/src/IProxyDictWithPool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b8225f596e0ff980d9df1459cbccd5c27edfcb54
--- /dev/null
+++ b/Control/SGTools/src/IProxyDictWithPool.cxx
@@ -0,0 +1,34 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: IProxyDictWithPool.cxx,v 1.1 2008-04-18 03:18:24 ssnyder Exp $
+/**
+ * @file SGTools/src/IProxyDictWithPool.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Mar, 2007
+ * @brief Combine IProxyDict and IStringPool.
+ */
+
+
+#include "SGTools/IProxyDictWithPool.h"
+
+
+/**
+ * @brief Test to see if the target of an ElementLink has moved.
+ * @param sgkey_in Original hashed key of the EL.
+ * @param index_in Original index of the EL.
+ * @param sgkey_out[out] New hashed key for the EL.
+ * @param index_out[out] New index for the EL.
+ * @return True if there is a remapping; false otherwise.
+ *
+ * The default implementation here always returns false.
+ */
+bool IProxyDictWithPool::tryELRemap (sgkey_t /*sgkey_in*/,
+                                     size_t /*index_in*/,
+                                     sgkey_t& /*sgkey_out*/,
+                                     size_t& /*index_out*/)
+{
+  return false;
+}
+
diff --git a/Control/SGTools/src/SGFolderItem.cxx b/Control/SGTools/src/SGFolderItem.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..ef7d496b4a544116f24e63465a72959f57d5cf57
--- /dev/null
+++ b/Control/SGTools/src/SGFolderItem.cxx
@@ -0,0 +1,12 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "SGTools/SGFolderItem.h"
+
+bool
+SG::FolderItem::isFolder() const {
+  return false;
+  //FIXME  return (m_id == ClassID_traits<Folder>::ID());
+}
+
diff --git a/Control/SGTools/src/SGToolsClids.cxx b/Control/SGTools/src/SGToolsClids.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..0b2040e8555801042bbeedc45d8c56b0239107de
--- /dev/null
+++ b/Control/SGTools/src/SGToolsClids.cxx
@@ -0,0 +1,9 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// anchor for the clids defined by this package
+
+#include "SGTools/BuiltinsClids.h"
+#include "SGTools/StlMapClids.h"
+#include "SGTools/StlVectorClids.h"
diff --git a/Control/SGTools/src/SGVersionedKey.cxx b/Control/SGTools/src/SGVersionedKey.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..c035d35eeaf3ad069283f8e1dc0d59fecbbd57a2
--- /dev/null
+++ b/Control/SGTools/src/SGVersionedKey.cxx
@@ -0,0 +1,113 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <stdexcept>
+#include <cassert>
+#include "SGTools/SGVersionedKey.h"
+using namespace SG;
+using namespace std;
+
+VersionedKey::~VersionedKey() {
+  //  if (m_versionKey) std::cout << "about to free " << 
+  //  m_versionKey << "@" << (void*)m_versionKey << 
+  // "@this " << this << std::endl;
+  free(m_versionKey); 
+}
+
+bool
+VersionedKey::isVersionedKey(const char * vkey) { 
+  return (vkey[0]==separator() && vkey[3]==separator());
+}
+
+bool 
+VersionedKey::isVersionedKey(const std::string& vkey) {
+  return isVersionedKey(vkey.c_str());
+}
+
+VersionedKey::VersionedKey(const char* key, unsigned char version) {
+  encode(key, version);
+}
+VersionedKey::VersionedKey(const std::string& key, unsigned char version) {
+  encode(key.c_str(), version);
+}
+VersionedKey::VersionedKey(const std::string& versionedKey) {
+  copyVK(versionedKey.c_str());
+}
+VersionedKey::VersionedKey(const char* versionedKey) {
+  copyVK(versionedKey);
+}
+VersionedKey::VersionedKey(const VersionedKey& versionedKey) :
+  m_versionKey(versionedKey.m_versionKey) {
+  versionedKey.m_versionKey=0; //a la auto-ptr
+}
+void VersionedKey::decode(char*& key, unsigned char& version) const {
+  key = m_versionKey+4;
+  version = (unsigned char)strtol(m_versionKey+1, NULL, 10);
+  assert(version <= 99);
+  // possibly faster, disgusting, version decoding
+  // equivalent to version = atoi(m_versionKey[2:3]);
+  //   char *cptr(m_versionKey+1);
+  //   if (*cptr>='0' && *cptr<='9') {
+  //     version = 10 * (*cptr - '0');
+  //     ++cptr;
+  //     if (*cptr>='0' && *cptr<='9') version += *cptr - '0';
+  //     else version = 0;
+  //   } else version = 0;
+}
+
+void VersionedKey::encode(const char* key, unsigned char version) {
+  assert(version <= 99);
+  m_versionKey = (char *)malloc(strlen(key)+5);
+  sprintf(m_versionKey, formatString(), version, key);
+}
+
+void VersionedKey::copyVK(const char* versionedKey) {
+  if (isVersionedKey(versionedKey)) {
+    m_versionKey = (char *)malloc(strlen(versionedKey)+1);
+    strcpy(m_versionKey, versionedKey);
+  }
+  else {
+    encode(versionedKey, 0);
+  }
+}
+unsigned char VersionedKey::version() const {
+  return (unsigned char)strtol(m_versionKey+1, NULL, 10);
+}
+/// @returns base key
+const char* VersionedKey::key() const { 
+  return m_versionKey+4; 
+}
+
+bool 
+VersionedKey::sameKey(const VersionedKey& vkey) const {
+  return (0 == strcmp(this->key(),vkey.key())); 
+}
+
+bool 
+VersionedKey::sameKey(const std::string& baseKey) const {
+  return (0 == strcmp(this->key(),baseKey.c_str())); 
+}
+
+bool 
+VersionedKey::sameKey(const char* baseKey) const {
+  return (0 == strcmp(this->key(),baseKey)); 
+}
+
+/// sort according to highest key version
+bool operator < (const SG::VersionedKey& lhs, const SG::VersionedKey& rhs) {
+  char *lhskey(0);
+  unsigned char lhsVersion(0);
+  lhs.decode(lhskey, lhsVersion);
+  unsigned char rhsVersion(0);
+  char *rhskey(0);
+  rhs.decode(rhskey, rhsVersion);
+  int keyCompare(strcmp(lhskey, rhskey));
+  return ( ( keyCompare < 0) ||
+	   ( (keyCompare == 0) && (lhsVersion < rhsVersion) ) ) ;
+	  
+}
diff --git a/Control/SGTools/src/StorableConversions.cxx b/Control/SGTools/src/StorableConversions.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..9f43eea2390729a37ebd2b75c6918b9cb62cf054
--- /dev/null
+++ b/Control/SGTools/src/StorableConversions.cxx
@@ -0,0 +1,78 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/** @file StorableConversions.cxx
+ *  @brief convert to and from a SG storable
+ * $Id: StorableConversions.cxx,v 1.2 2008-04-08 16:05:32 ssnyder Exp $
+ * @author ATLAS Collaboration
+ **/
+
+#include "SGTools/StorableConversions.h"
+
+
+namespace SG {
+
+
+/**
+ * @brief Try to get the pointer back from a @a DataObject,
+ *        converted to be of type @a clid.
+ * @param pDObj The @a DataObject.
+ * @param clid The ID of the class to which to convert.
+ * @param irt To be called if we make a new instance.
+ * @param isConst True if the object being converted is regarded as const.
+ *
+ * Only works if the @a DataObject is a @a DataBucket.
+ * Returns 0 on failure,
+ */
+void* fromStorable(DataObject* pDObj, CLID clid,
+                   IRegisterTransient*irt/*= 0*/,
+                   bool isConst /*= true*/)
+{
+  // Try to use BaseInfo information to convert pointers.
+  DataBucketBase* b = dynamic_cast<DataBucketBase*>(pDObj);
+  if (b)
+    return b->cast (clid, irt, isConst);
+  return 0;
+}
+
+
+/**
+ * @brief Try to get the pointer back from a @a DataObject,
+ *        converted to be of type @a clid.
+ * @param pDObj The @a DataObject.
+ * @param clid The ID of the class to which to convert.
+ * @param irt To be called if we make a new instance.
+ * @param isConst True if the object being converted is regarded as const.
+ *
+ * Only works if the @a DataObject is a @a DataBucket.
+ * Returns 0 on failure,
+ */
+void* Storable_cast(DataObject* pDObj, CLID clid,
+                    IRegisterTransient* irt /*= 0*/,
+                    bool isConst /*= true*/)
+{
+  return fromStorable (pDObj, clid, irt, isConst);
+}
+
+
+/**
+ * @brief Try to get the pointer back from a @a DataObject,
+ *        converted to be of type @a clid.
+ * @param pDObj The @a DataObject.
+ * @param clid The ID of the class to which to convert.
+ * @param irt To be called if we make a new instance.
+ * @param isConst True if the object being converted is regarded as const.
+ *
+ * Only works if the @a DataObject is a @a DataBucket.
+ * Returns 0 on failure,
+ */
+const void* Storable_cast(const DataObject* pDObj, CLID clid,
+                          IRegisterTransient* irt /*= 0*/,
+                          bool isConst /*= true*/)
+{
+  return fromStorable (const_cast<DataObject*> (pDObj), clid, irt, isConst);
+}
+
+
+} // namespace SG
diff --git a/Control/SGTools/src/StringPool.cxx b/Control/SGTools/src/StringPool.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..6ebfe4b7dfd979ad15fc8cd902ebaef35e000a14
--- /dev/null
+++ b/Control/SGTools/src/StringPool.cxx
@@ -0,0 +1,224 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: StringPool.cxx,v 1.3 2007-12-10 22:20:03 ssnyder Exp $
+/**
+ * @file  SGTools/StringPool.cxx
+ * @author scott snyder
+ * @date Mar 2007
+ * @brief Maintain a mapping of strings to 64-bit ints.
+ */
+
+
+#include "SGTools/StringPool.h"
+#include "SGTools/crc64.h"
+#include "CxxUtils/unordered_map.h"
+#include <map>
+#include <cstdlib>
+#include <iostream>
+#include <iomanip>
+
+
+namespace SG {
+
+
+//***************************************************************************
+// Implementation class.
+//
+
+
+class StringPoolImpl
+{
+public:
+  /// Remember an additional mapping from key to string.
+  bool registerKey (StringPool::sgkey_t key,
+                    const std::string& str,
+                    StringPool::sgaux_t aux);
+
+  /// Find the string corresponding to a given key.
+  const std::string* keyToString (StringPool::sgkey_t key,
+                                  StringPool::sgaux_t& aux) const;
+
+  /// Debugging dump.  Write to stdout.
+  void dump() const;
+
+private:
+  // Hash function for the key.
+  // Just cast the low bits to a size_t.
+  struct keyhash
+  {
+    std::size_t operator() (StringPool::sgkey_t key) const
+    { return static_cast<std::size_t> (key); }
+  };
+
+  // The key hash table.
+  typedef std::pair<StringPool::sgaux_t, std::string> pair_t;
+  typedef SG::unordered_map<StringPool::sgkey_t, pair_t, keyhash> keymap_t;
+  keymap_t m_keymap;
+};
+
+
+/**
+ * @brief Remember an additional mapping from key to string.
+ * @param key The key to enter.
+ * @param str The string to enter.
+ * @param aux Auxiliary data to include along with the string.
+ * @return True if successful; false if the @c key already
+ *         corresponds to a different string.
+ */
+bool StringPoolImpl::registerKey (StringPool::sgkey_t key,
+                                  const std::string& str,
+                                  StringPool::sgaux_t aux)
+{
+  StringPoolImpl::keymap_t::iterator i = m_keymap.find (key);
+  if (i == m_keymap.end()) {
+    pair_t& p = m_keymap[key];
+    p.first = aux;
+    p.second = str;
+  }
+  else if (i->second.first != aux || i->second.second != str)
+    return false;
+  return true;
+}
+
+
+/**
+ * @brief Find the string corresponding to a given key.
+ * @param key The key to look up.
+ * @param aux[out] Auxiliary data associated with the key.
+ * @return Pointer to the string found, or null.
+ *         We can find keys as long as the corresponding string
+ *         was given to either @c stringToKey() or @c registerKey().
+ */
+const std::string*
+StringPoolImpl::keyToString (StringPool::sgkey_t key,
+                             StringPool::sgaux_t& aux) const
+{
+  StringPoolImpl::keymap_t::const_iterator i = m_keymap.find (key);
+  if (i != m_keymap.end()) {
+    aux = i->second.first;
+    return &i->second.second;
+  }
+  return 0;
+}
+
+
+/**
+ * @brief Debugging dump.  Write to cout.
+ */
+void StringPoolImpl::dump() const
+{
+  for (keymap_t::const_iterator i = m_keymap.begin();
+       i != m_keymap.end();
+       ++i)
+  {
+    std::cout << std::hex << std::setw(18) << i->first << " "
+              << std::dec << std::setw(9) << i->second.first << " "
+              << i->second.second << "\n";
+  }
+}
+
+
+//***************************************************************************
+// StringPool class.
+//
+
+/**
+ * @brief Constructor.
+ */
+StringPool::StringPool()
+  : m_impl (new StringPoolImpl)
+{
+}
+
+
+/**
+ * @brief Destructor.
+ */
+StringPool::~StringPool()
+{
+  delete m_impl;
+}
+
+
+/**
+ * @brief Find the key for a string.
+ * @param str The string to look up.
+ * @param aux Auxiliary data to include along with the string.
+ * @return A key identifying the string.
+ *         A given string will always return the same key.
+ *         Will abort in case of a hash collision!
+ */
+StringPool::sgkey_t StringPool::stringToKey (const std::string& str,
+                                             sgaux_t aux /*= 0*/)
+{
+  uint64_t crc = crc64 (str);
+  if (aux) crc = crc64addint (crc, aux);
+  sgkey_t key = (crc & sgkey_t_max);
+  if (!m_impl->registerKey (key, str, aux))
+    std::abort();
+  return key;
+}
+
+
+/**
+ * @brief Find the string corresponding to a given key.
+ * @param key The key to look up.
+ * @return Pointer to the string found, or null.
+ *         We can find keys as long as the corresponding string
+ *         was given to either @c stringToKey() or @c registerKey().
+ */
+const std::string* StringPool::keyToString (sgkey_t key) const
+{
+  sgaux_t aux;
+  return m_impl->keyToString (key, aux);
+}
+
+
+/**
+ * @brief Find the string corresponding to a given key.
+ * @param key The key to look up.
+ * @param aux[out] Auxiliary data associated with the key.
+ * @return Pointer to the string found, or null.
+ *         We can find keys as long as the corresponding string
+ *         was given to either @c stringToKey() or @c registerKey().
+ */
+const std::string* StringPool::keyToString (sgkey_t key,
+                                            sgaux_t& aux) const
+{
+  return m_impl->keyToString (key, aux);
+}
+
+
+/**
+ * @brief Remember an additional mapping from key to string.
+ * @param key The key to enter.
+ * @param str The string to enter.
+ * @param aux Auxiliary data to include along with the string.
+ * @return True if successful; false if the @c key already
+ *         corresponds to a different string.
+ *
+ * This registers an additional mapping from a key to a string;
+ * it can be found later through @c lookup() on the string.
+ */
+bool StringPool::registerKey (sgkey_t key,
+                              const std::string& str,
+                              sgaux_t aux /*= 0*/)
+{
+  // Make sure the primary mapping is registered first.
+  stringToKey (str, aux);
+  return m_impl->registerKey (key, str, aux);
+}
+
+
+/**
+ * @brief Debugging dump.  Write to cout.
+ */
+void StringPool::dump () const
+{
+  m_impl->dump();
+}
+
+
+} // namespace SG
diff --git a/Control/SGTools/src/T2pMap.cxx b/Control/SGTools/src/T2pMap.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..03a7c3eaccb423cc803841703b43c69a49a69cbf
--- /dev/null
+++ b/Control/SGTools/src/T2pMap.cxx
@@ -0,0 +1,17 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "SGTools/T2pMap.h"
+using namespace SG;
+std::vector<DataProxy*> T2pMap::pacReport() const {
+  std::vector<DataProxy*> notAccessed;
+  if (m_pac) {
+    t2p::const_iterator i(m_t2p.begin()), e(m_t2p.end());
+    while (i != e) {
+      if (!m_pac->accessed(i->first)) notAccessed.push_back(i->second);
+      ++i;
+    }
+  }
+  return notAccessed;
+}
diff --git a/Control/SGTools/src/TransientAddress.cxx b/Control/SGTools/src/TransientAddress.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..5ad9091c0e64c6ecd9259da05de4230a754748f7
--- /dev/null
+++ b/Control/SGTools/src/TransientAddress.cxx
@@ -0,0 +1,95 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "SGTools/TransientAddress.h"
+#include "AthenaKernel/IAddressProvider.h"
+#include "GaudiKernel/IOpaqueAddress.h"
+
+#include <assert.h>
+
+using SG::TransientAddress;
+
+// Default Constructor:
+TransientAddress::TransientAddress()
+  : m_clid(0), m_name(""), m_address(0), m_clearAddress(true),
+    m_consultProvider(false), m_pAddressProvider(0), m_storeID(StoreID::UNKNOWN),
+    m_sgkey(0)
+{ }
+
+// Constructor with CLID and string key:
+// (typically used through a StoreGate::record()
+TransientAddress::TransientAddress(const CLID& id, const std::string& key)
+  : m_clid(id), m_name(key), m_address(0), m_clearAddress(true),
+    m_consultProvider(false), m_pAddressProvider(0), m_storeID(StoreID::UNKNOWN),
+    m_sgkey(0)
+{ 
+  if (id != CLID_NULL)
+    m_transientID.insert(id);
+}
+
+// Constructor with CLID, string key and IOpaqueAddress:
+// (typically used by a ProxyProvider)
+TransientAddress::TransientAddress(const CLID& id, const std::string& key, 
+				   IOpaqueAddress* addr, 
+				   bool clearAddress)
+  : m_clid(id), m_name(key), m_address(0), m_clearAddress(clearAddress),
+    m_consultProvider(true), m_pAddressProvider(0), m_storeID(StoreID::UNKNOWN),
+    m_sgkey(0)
+{ 
+  if (id != CLID_NULL)
+    m_transientID.insert(id);
+  setAddress(addr);
+}
+
+// Destructor
+TransientAddress::~TransientAddress() 
+{ 
+  setAddress(0);
+}
+
+
+/**
+ * @brief Set the CLID / key.
+ * @param id The new CLID.
+ * @param key The new StoreGate key.
+ *
+ * This will only succeed if the clid/key are currently clear.
+ */
+void TransientAddress::setID (CLID id, const std::string& key)
+{
+  assert (m_clid == CLID_NULL && m_name.empty() && m_transientID.empty() &&
+          m_transientAlias.empty());
+  m_clid = id;
+  m_name = key;
+  if (id != CLID_NULL)
+    m_transientID.insert(id);
+}
+
+/// set IOpaqueAddress
+void TransientAddress::setAddress(IOpaqueAddress* pAddress)
+{ 
+  if (0 != pAddress) pAddress->addRef();
+  if (0 != m_address) m_address->release();
+  m_address = pAddress;
+}
+
+bool TransientAddress::isValid()
+{
+  if (0 != address()) return true;
+
+  // FIXME CGL
+//    if (!m_consultProvider) {
+//      if ( m_clid != 0 && m_name != "" ) { return true; }
+//    }
+  if (m_consultProvider && 0 != provider()) {
+    if ((provider()->updateAddress(storeID(), this)).isSuccess())
+      return true;
+  }
+  return false;
+}
+
+
+
+
+
diff --git a/Control/SGTools/src/crc64.cxx b/Control/SGTools/src/crc64.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..6081bbec8a8c382e209084552d5ab1afa8bfe9e7
--- /dev/null
+++ b/Control/SGTools/src/crc64.cxx
@@ -0,0 +1,126 @@
+// $Id: crc64.cxx,v 1.2 2007-03-08 02:02:06 ssnyder Exp $
+/**
+ * @file  SGTools/crc64.cxx
+ * @author scott snyder, originally from David T. Jones
+ * @date Mar 2007
+ * @brief A CRC-64 implementation.
+ */
+/*
+ * Original comments:
+ * Improved calculation of CRC-64 values for protein sequences
+ * By David T. Jones (dtj@cs.ucl.ac.uk)  - September 28th 2002
+ * 
+ * Modified from code at URL:
+ * ftp://ftp.ebi.ac.uk/pub/software/swissprot/Swissknife/old/SPcrc.tar.gz
+ *
+ * Changed to C++ and moved into a namespace.
+ */
+
+
+#include "SGTools/crc64.h"
+#include <cstdio>
+using namespace std;
+
+
+// I don't have a citation for the source of this polynomial.
+// Maybe should replace it with the ECMA DLT poly?
+#define POLY64REV     0x95AC9329AC4BC9B5ULL
+#define INITIALCRC    0xFFFFFFFFFFFFFFFFULL
+
+// Original SWISSPROT/TrEMBL poly.  Shown to be weak.
+//#define POLY64REV	0xd800000000000000ULL
+//#define INITIALCRC	0x0000000000000000ULL
+
+
+namespace {
+
+bool crc_init = false;
+uint64_t CRCTable[256];
+
+// Initialize the CRC table.
+void init_table()
+{
+  crc_init = true;
+  for (int i = 0; i < 256; i++)
+  {
+    uint64_t part = i;
+    for (int j = 0; j < 8; j++)
+    {
+      if (part & 1)
+        part = (part >> 1) ^ POLY64REV;
+      else
+        part >>= 1;
+    }
+    CRCTable[i] = part;
+  }
+}
+
+} // anonymous namespace
+
+
+namespace SG {
+
+
+/**
+ * @brief Find the CRC-64 of a string.
+ * @param str The string to hash.
+ */
+uint64_t crc64 (const std::string& str)
+{
+  if (!crc_init)
+    init_table();
+
+  uint64_t crc = INITIALCRC;
+  const char* seq = str.data();
+  const char* end = seq + str.size();
+  while (seq < end)
+    crc = CRCTable[(crc ^ *seq++) & 0xff] ^ (crc >> 8);
+  return crc;
+}
+
+
+/**
+ * @brief Extend a previously-calculated CRC to include an int.
+ * @param crc The previously-calculated CRC.
+ * @param x The integer to add.
+ * @return The new CRC.
+ */
+uint64_t crc64addint (uint64_t crc, unsigned int x)
+{
+  if (!crc_init)
+    init_table();
+
+  while (x > 0) {
+    crc = CRCTable[(crc ^ x) & 0xff] ^ (crc >> 8);
+    x >>= 8;
+  }
+  return crc;
+}
+
+
+/**
+ * @brief Format a CRC-64 as a string.
+ * @param crc The CRC to format.
+ */
+std::string crc64format (uint64_t crc)
+{
+  char buf[64];
+  sprintf (buf, "%08X%08X",
+           (unsigned)((crc>>32)&0xffffffff), (unsigned)(crc&0xffffffff));
+  return buf;
+}
+
+
+/**
+ * @brief Return a CRC-64 digest of a string.
+ * @param str The string to hash.
+ * @return The CRC-64 digest of the string.
+ *         This is the hash code, expressed as hex as a string.
+ */
+std::string crc64digest (const std::string& str)
+{
+  return crc64format (crc64 (str));
+}
+
+
+} // namespace SG
diff --git a/Control/SGTools/src/exceptions.cxx b/Control/SGTools/src/exceptions.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..dad034bdd7b874e73a6261d2de9261e33d7ac80d
--- /dev/null
+++ b/Control/SGTools/src/exceptions.cxx
@@ -0,0 +1,100 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file SGTools/src/exceptions.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Nov, 2013
+ * @brief Exceptions that can be thrown by SGTools.
+ */
+
+
+#include "SGTools/exceptions.h"
+#include "GaudiKernel/System.h"
+#include <sstream>
+#include <string>
+
+
+namespace SG {
+
+
+/// Helper: Format exception string.
+std::string excBadDataProxyCast_format (CLID id, const std::type_info& tid)
+{
+  std::ostringstream os;
+  os << "Bad cast of DataProxy with CLID " << id
+     << " to type " << System::typeinfoName (tid);
+  return os.str();
+}
+
+
+/**
+ * @brief Constructor.
+ * @param id CLID of the DataProxy.
+ * @param tid Type to which we're trying to convert the object.
+ */
+ExcBadDataProxyCast::ExcBadDataProxyCast (CLID id, const std::type_info& tid)
+  : m_what (excBadDataProxyCast_format (id, tid))
+{
+}
+
+
+/**
+ * @brief Return the message for this exception.
+ */
+const char* ExcBadDataProxyCast::what() const throw()
+{
+  return m_what.c_str();
+}
+
+
+/**
+ * @brief Throw an ExcBadDataProxyCast exception.
+ * @param id CLID of the DataProxy.
+ * @param tid Type to which we're trying to convert the object.
+ */
+void throwExcBadDataProxyCast (CLID id, const std::type_info& tid)
+{
+  throw ExcBadDataProxyCast (id, tid);
+}
+
+
+//*************************************************************************
+
+
+/// Helper: Format exception string.
+std::string excProxyCollision_format (CLID id,
+                                      const std::string& key,
+                                      CLID primary_id,
+                                      const std::string& primary_key)
+{
+  std::ostringstream os;
+  os << "ExcProxyCollision: proxy collision for clid/key "
+     << id << " / " << key
+     << " (primary " << primary_id << " / " << primary_key << ").";
+  return os.str();
+}
+
+
+/**
+ * @brief Constructor.
+ * @param id CLID we're trying to set on the dummy proxy.
+ * @param key Key we're trying to set on the dummy proxy.
+ * @param primary_id CLID of the existing proxy.
+ * @param primary_key Key of the existing proxy.
+ */
+ExcProxyCollision::ExcProxyCollision (CLID id,
+                                      const std::string& key,
+                                      CLID primary_id,
+                                      const std::string& primary_key)
+  : std::runtime_error (excProxyCollision_format (id,
+                                                  key,
+                                                  primary_id,
+                                                  primary_key))
+{
+}
+
+
+} // namespace SG
diff --git a/Control/SGTools/test/BaseInfo_test.cxx b/Control/SGTools/test/BaseInfo_test.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..b781bde748285487f3cb62e367b46cdba4684fad
--- /dev/null
+++ b/Control/SGTools/test/BaseInfo_test.cxx
@@ -0,0 +1,341 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file  SGTools/BaseInfo_test.cxx
+ * @author scott snyder
+ * @date A while ago.
+ * @brief Regression test for BaseInfo.
+ */
+
+
+#undef NDEBUG
+
+#include "SGTools/BaseInfo.h"
+#include "SGTools/CLASS_DEF.h"
+#include "boost/assign/list_of.hpp"
+#include <iostream>
+#include <algorithm>
+#include <cassert>
+
+using std::cout;
+using boost::assign::list_of;
+
+struct AA
+{
+  AA (int the_x=0): x(the_x) {}
+  ~AA() { }
+  int x;
+};
+struct BB : public AA
+{
+  BB (int the_x=0) : AA(the_x) {}
+};
+struct CC : public BB
+{
+  CC (int the_x=0) : BB(the_x) {}
+};
+
+SG_BASE(BB, AA);
+SG_BASE(CC, BB);
+
+CLASS_DEF (AA, 1111, 2)
+CLASS_DEF (BB, 1112, 2)
+CLASS_DEF (CC, 1113, 2)
+
+struct M
+{
+  M (int the_x=0) : x(the_x) {}
+  virtual ~M() { }
+  int x;
+};
+struct N : virtual public M 
+{
+  N (int the_x=0) : M(the_x) {}
+};
+struct O : virtual public M
+{
+  O (int the_x=0) : M(the_x) {}
+};
+struct P : virtual public N, virtual public O
+{
+  P (int the_x=0) : M(the_x) {}
+};
+
+CLASS_DEF (M, 1114, 2)
+CLASS_DEF (N, 1115, 2)
+CLASS_DEF (O, 1116, 2)
+CLASS_DEF (P, 1117, 2)
+
+SG_BASE (N, SG_VIRTUAL (M));
+SG_BASE (O, SG_VIRTUAL (M));
+SG_BASES2 (P, SG_VIRTUAL (N), SG_VIRTUAL (O));
+
+struct X1 {};
+struct X2 : public X1 {};
+SG_BASE (X2, X1);
+
+struct Q : virtual public M
+{
+  Q (int the_x=0) : M(the_x) {}
+};
+struct R : virtual public N, virtual public O, virtual public Q
+{
+  R (int the_x=0) : M(the_x) {}
+};
+
+CLASS_DEF (Q, 1118, 2)
+CLASS_DEF (R, 1119, 2)
+
+SG_BASE (Q, SG_VIRTUAL (M));
+SG_BASES3 (R, SG_VIRTUAL (N),
+           SG_VIRTUAL (O),
+           SG_VIRTUAL (Q));
+
+
+struct I1 : public AA {};
+struct I2 : public AA {};
+SG_BASE (I1, AA);
+SG_BASE (I2, AA);
+CLASS_DEF (I2, 1120, 2)
+
+struct J : public AA, virtual public X1, public M {};
+SG_BASE(J, AA);
+SG_ADD_BASE(J, SG_VIRTUAL(X1));
+SG_ADD_BASE(J, M);
+
+struct K : public AA {};
+SG_ADD_BASE(K, AA);
+
+
+int test1()
+{
+  std::cout << "test1\n";
+
+  typedef SG::BaseInfo<CC> CC_C;
+  typedef SG::BaseInfo<R>  R_C;
+
+  std::vector<CLID> clids;
+  clids = CC_C::get_bases();
+  std::vector<CLID> exp1 = list_of
+    (ClassID_traits<CC>::ID())
+    (ClassID_traits<BB>::ID())
+    (ClassID_traits<AA>::ID());
+  std::sort (exp1.begin(), exp1.end());
+  assert (clids == exp1);
+
+  std::vector<const std::type_info*> tinfos;
+  tinfos = CC_C::get_ti_bases();
+  std::vector<const std::type_info*> exp1ti = list_of
+    (&typeid(CC))
+    (&typeid(BB))
+    (&typeid(AA));
+  std::sort (exp1ti.begin(), exp1ti.end());
+  assert (tinfos == exp1ti);
+
+  clids = R_C::get_bases();
+  std::vector<CLID> exp2 = list_of
+    (ClassID_traits<M>::ID())
+    (ClassID_traits<N>::ID())
+    (ClassID_traits<O>::ID())
+    (ClassID_traits<Q>::ID())
+    (ClassID_traits<R>::ID());
+  std::sort (exp2.begin(), exp2.end());
+  assert (clids == exp2);
+
+  tinfos = R_C::get_ti_bases();
+  std::vector<const std::type_info*> exp2ti = list_of
+    (&typeid(M))
+    (&typeid(N))
+    (&typeid(O))
+    (&typeid(Q))
+    (&typeid(R));
+  std::sort (exp2ti.begin(), exp2ti.end());
+  assert (tinfos == exp2ti);
+
+  SG::BaseInfoBase::castfn_t* castfn;
+
+  M* m0 = new M;
+  R* r1 = new R;
+  M* m1 = r1;
+  assert ((long)m1 != (long)r1);
+  M* m2 = (M*)R_C::cast (r1, ClassID_traits<M>::ID());
+  assert ((long)m1 == (long)m2);
+  m2 = (M*)R_C::cast (r1, typeid (M));
+  assert ((long)m1 == (long)m2);
+  R* r2 = (R*)R_C::castTo (m1, ClassID_traits<M>::ID());
+  assert ((long)r1 == (long)r2);
+  r2 = (R*)R_C::castTo (m1, typeid (M));
+  assert ((long)r1 == (long)r2);
+  r2 = (R*)R_C::castTo (m0, typeid (M));
+  assert (r2 == 0);
+
+  castfn = R_C::castfn (ClassID_traits<M>::ID());
+  assert ((long)m1 == (long)castfn(r1));
+  castfn = R_C::castfn (typeid (M));
+  assert ((long)m1 == (long)castfn(r1));
+  castfn = R_C::castfnTo (ClassID_traits<M>::ID());
+  assert ((long)r1 == (long)castfn(m1));
+  castfn = R_C::castfnTo (typeid (M));
+  assert ((long)r1 == (long)castfn(m1));
+  assert (0 == (long)castfn(m0));
+
+  assert (R_C::cast (r1, ClassID_traits<AA>::ID()) == 0);
+  assert (R_C::cast (r1, typeid (AA)) == 0);
+  assert (R_C::castTo (r1, ClassID_traits<AA>::ID()) == 0);
+  assert (R_C::castTo (r1, typeid (AA)) == 0);
+  assert (R_C::castfn (ClassID_traits<AA>::ID()) == 0);
+  assert (R_C::castfn (typeid (AA)) == 0);
+  assert (R_C::castfnTo (ClassID_traits<AA>::ID()) == 0);
+  assert (R_C::castfnTo (typeid (AA)) == 0);
+
+  assert (R_C::is_base (ClassID_traits<M>::ID()));
+  assert (R_C::is_base (typeid (M)));
+
+  assert (!R_C::is_base (ClassID_traits<AA>::ID()));
+  assert (!R_C::is_base (typeid (AA)));
+
+  assert (CC_C::is_base (ClassID_traits<AA>::ID()));
+  assert (CC_C::is_base (typeid (AA)));
+
+  assert (R_C::is_virtual (ClassID_traits<M>::ID()));
+  assert (R_C::is_virtual (typeid (M)));
+
+  assert (!CC_C::is_virtual (ClassID_traits<AA>::ID()));
+  assert (!CC_C::is_virtual (typeid (AA)));
+
+  typedef SG::BaseInfo<X2> X_C;
+  assert (X_C::is_base (typeid (X1)));
+  X2* x2 = new X2;
+  X1* x1 = (X1*)X_C::cast (x2, typeid (X1));
+  assert (x1 == x2);
+  X2* x2a = (X2*)X_C::castTo (x1, typeid (X1));
+  assert (x2a == 0); // castTo doesn't work now for non-polymorphic classes.
+
+  clids = SG::BaseInfoBase::find (ClassID_traits<CC>::ID())->get_bases();
+  assert (clids == exp1);
+  tinfos = SG::BaseInfoBase::find (ClassID_traits<CC>::ID())->get_ti_bases();
+  assert (tinfos == exp1ti);
+
+  clids = CC_C::baseinfo().get_bases();
+  assert (clids == exp1);
+  tinfos = CC_C::baseinfo().get_ti_bases();
+  assert (tinfos == exp1ti);
+
+  clids = SG::BaseInfoBase::find (typeid (CC))->get_bases();
+  assert (clids == exp1);
+  tinfos = SG::BaseInfoBase::find (typeid (CC))->get_ti_bases();
+  assert (tinfos == exp1ti);
+
+  assert (SG::BaseInfoBase::find (typeid(CC))->clid() ==
+          ClassID_traits<CC>::ID());
+  assert (SG::BaseInfoBase::find (typeid(CC))->typeinfo() == typeid(CC));
+
+  assert (SG::BaseInfoBase::find (99999) == 0);
+  assert (SG::BaseInfoBase::find (typeid(int)) == 0);
+
+  assert (typeid(SG::BaseType<SG::Bases<BB>::Base1>::type) == typeid(AA));
+  assert (typeid(SG::BaseType<SG::Bases<BB>::Base1>::is_virtual) ==
+          typeid(boost::false_type));
+
+  assert (typeid(SG::BaseType<SG::Bases<N>::Base1>::type) == typeid(M));
+  assert (typeid(SG::BaseType<SG::Bases<N>::Base1>::is_virtual) ==
+          typeid(boost::true_type));
+
+  std::vector<CLID> exp3 = list_of
+    (ClassID_traits<AA>::ID());
+  clids = SG::BaseInfoBase::find (typeid (I1))->get_bases();
+  assert (clids == exp3);
+
+  std::vector<const std::type_info*> exp3ti = list_of
+    (&typeid (AA))
+    (&typeid (I1));
+  std::sort (exp3ti.begin(), exp3ti.end());
+  tinfos = SG::BaseInfoBase::find (typeid (I1))->get_ti_bases();
+  assert (tinfos == exp3ti);
+
+  std::vector<CLID> exp4 = list_of
+    (ClassID_traits<AA>::ID())
+    (ClassID_traits<I2>::ID());
+  clids = SG::BaseInfoBase::find (ClassID_traits<I2>::ID())->get_bases();
+  assert (clids == exp4);
+
+  std::vector<const std::type_info*> exp4ti = list_of
+    (&typeid (AA))
+    (&typeid (I2));
+  std::sort (exp4ti.begin(), exp4ti.end());
+  tinfos = SG::BaseInfoBase::find (typeid (I2))->get_ti_bases();
+  assert (tinfos == exp4ti);
+
+  const SG::BaseInfoBase* jbib = SG::BaseInfoBase::find (typeid (J));
+  tinfos = jbib->get_ti_bases();
+  std::vector<const std::type_info*> exp5ti = list_of
+    (&typeid (AA))
+    (&typeid (X1))
+    (&typeid (M))
+    (&typeid (J));
+  std::sort (exp5ti.begin(), exp5ti.end());
+  std::sort (tinfos.begin(), tinfos.end());
+  assert (tinfos == exp5ti);
+  assert (!jbib->is_virtual (typeid (AA)));
+  assert ( jbib->is_virtual (typeid (X1)));
+  assert (!jbib->is_virtual (typeid (M)));
+
+  const SG::BaseInfoBase* kbib = SG::BaseInfoBase::find (typeid (K));
+  tinfos = kbib->get_ti_bases();
+  std::vector<const std::type_info*> exp6ti = list_of
+    (&typeid (AA))
+    (&typeid (K));
+  std::sort (exp6ti.begin(), exp6ti.end());
+  std::sort (tinfos.begin(), tinfos.end());
+  assert (tinfos == exp6ti);
+    
+  return 0;
+}
+
+
+class KCopyConversion
+  : public SG::CopyConversion<K, M>
+{
+public:
+  void convert (const K& src, M& dst) const
+  { dst.x = src.x; }
+};
+
+SG_ADD_COPY_CONVERSION(K, KCopyConversion);
+
+
+// Test copying conversions.
+void test2()
+{
+  std::cout << "test2\n";
+  const SG::BaseInfoBase& bib = SG::BaseInfo<K>::baseinfo();
+  std::vector<CLID> clids = bib.get_copy_conversions();
+  std::vector<CLID> exp1 = list_of
+    (ClassID_traits<M>::ID());
+  assert (clids == exp1);
+
+  const SG::CopyConversionBase* b = bib.copy_conversion (clids[0]);
+  assert (b == bib.copy_conversion (typeid (M)));
+  assert (0 == bib.copy_conversion (typeid (X1)));
+  assert (0 == bib.copy_conversion (typeid (Q)));
+  assert (0 == bib.copy_conversion (ClassID_traits<Q>::ID()));
+
+  K k;
+  k.x = 10;
+  M m;
+  m.x = 0;
+  b->convertUntyped (&k, &m);
+  assert (m.x == 10);
+}
+
+
+int main()
+{
+  test1();
+  test2();
+  return 0;
+}
+
diff --git a/Control/SGTools/test/CLIDRegistry_test.cxx b/Control/SGTools/test/CLIDRegistry_test.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..739f122682c46b041cc60973ca13e09bbdf4e969
--- /dev/null
+++ b/Control/SGTools/test/CLIDRegistry_test.cxx
@@ -0,0 +1,52 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/** @file CLIDRegistry_test.cxx 
+ *  @brief unit test for CLIDRegistry
+ *
+ * $Id: CLIDRegistry_test.cxx,v 1.2 2009-01-19 17:02:55 binet Exp $
+ * @author Paolo Calafiura <pcalafiura@lbl.gov> - ATLAS Collaboration
+ */
+
+/* #define COMPILEFAIL 1 */
+
+#undef NDEBUG
+
+#include "SGTools/CLIDRegistry.h"
+
+#include <algorithm>
+#include <cassert>
+#include <iostream>
+
+using namespace std;
+
+#include <boost/tuple/tuple.hpp>
+using boost::get;
+#include "AthenaKernel/tools/AthenaPackageInfo.h"
+
+int main () {
+  cerr << "*** CLIDRegistry_test starts ***" <<endl;
+  //reset newEntries before we start counting
+  std::pair<CLIDRegistry::const_iterator, CLIDRegistry::const_iterator>  er =
+    CLIDRegistry::newEntries();
+  Athena::PackageInfo info(PACKAGE_VERSION);
+#ifdef COMPILEFAIL
+  CLIDRegistry::addEntry<12>("Foo", info, "Foo");
+  //no upper limit  CLIDRegistry::addEntry<1245736740>("Foo", info);
+#endif
+  CLIDRegistry::addEntry<1234>("Foo", info, "Foo");
+  CLIDRegistry::addEntry<4321>("Bar", info, "Bar");
+  assert(CLIDRegistry::hasNewEntries());
+  er = CLIDRegistry::newEntries();
+  assert( distance(er.first, er.second) == 2 );
+  assert( get<0>(*(CLIDRegistry::end()-2)) == 1234 );
+  assert( get<1>(*(CLIDRegistry::end()-2)) == "Foo" );
+  assert( get<2>(*(CLIDRegistry::end()-2)).name() == "SGTools" );
+  CLIDRegistry::addEntry<43213>("Baz", info, "Baz");
+  er = CLIDRegistry::newEntries();
+  assert( distance(er.first, er.second) == 1 );
+  assert( !CLIDRegistry::hasNewEntries());
+  cerr << "*** CLIDRegistry_test OK ***" <<endl;
+  return 0;
+}
diff --git a/Control/SGTools/test/ClassName_test.cxx b/Control/SGTools/test/ClassName_test.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..efd1eebcd8063f62d3cb014547ac73ea105f2d83
--- /dev/null
+++ b/Control/SGTools/test/ClassName_test.cxx
@@ -0,0 +1,25 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include <cassert>
+#include "SGTools/ClassName.h"
+
+class A {};
+class B {};
+template <class T> class C {};
+
+template <>
+class ClassName<B>
+{
+public:
+  static std::string name() { return "fooB"; }
+};
+
+int main()
+{
+  assert (ClassName<A>::name() == "A");
+  assert (ClassName<C<C<A> > >::name() == "C<C<A> >");
+  assert (ClassName<B>::name() == "fooB");
+  return 0;
+}
diff --git a/Control/SGTools/test/DataBucket_test.cxx b/Control/SGTools/test/DataBucket_test.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..14de4c273c28f7b197380a16a2b6b20e0bd64614
--- /dev/null
+++ b/Control/SGTools/test/DataBucket_test.cxx
@@ -0,0 +1,408 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#undef NDEBUG
+
+#include "SGTools/BuiltinsClids.h"
+#include "SGTools/StlVectorClids.h"
+#include "SGTools/StlMapClids.h"
+#include "SGTools/DataBucket.h"
+#include "SGTools/StorableConversions.h"
+#include "AthenaKernel/ILockable.h"
+#include <iostream>
+using namespace std;
+using namespace SG;
+
+/*FIXME can get it from TestTools circ package dep */
+#include <cassert>
+#define SGASSERTERROR( FALSEEXPR )   \
+    std::cerr << "Now we expect to see an error message:" << std::endl \
+              << "----Error Message Starts--->>" << std::endl; \
+    assert(!FALSEEXPR); \
+    std::cerr<< "<<---Error Message Ends-------" << std::endl
+
+
+#include "GaudiKernel/DataObject.h"
+class GaudiDataObj : public DataObject {
+ 
+public: 
+  static int count;
+ 
+  GaudiDataObj(): DataObject(), m_val(0) { ++count; };
+  GaudiDataObj(int i): DataObject(), m_val(i) { ++count; };
+  virtual ~GaudiDataObj(){ --count; };
+
+  static const CLID& classID() {
+    static const CLID _ID = 8010;
+    return _ID; }
+  virtual const CLID& clID() const { return classID(); }
+
+  void val(int i) { m_val = i; }
+  int val() const { return m_val; }
+
+private:
+  int m_val;
+};
+int GaudiDataObj::count = 0;
+
+class WrongType {};
+
+class AbstractType {
+public:
+  virtual ~AbstractType() {}
+  virtual void abstractMethod()=0;
+};
+
+class AbstractDataObj : public DataObject {
+public:
+  static const CLID& classID() {
+    static const CLID _ID = 8011;
+    return _ID; }
+  virtual const CLID& clID() const { return classID(); }
+  virtual void abstractMethod()=0;
+};
+
+class MyDataObj {
+ 
+public: 
+  static int count;
+
+  MyDataObj(): m_val(0) { ++count; };
+  MyDataObj(int i): m_val(i) { ++count; }
+  ~MyDataObj(){ --count; }
+
+  void val(int i) { m_val = i; }
+  int val() const { return m_val; }
+
+private:
+  int m_val;
+};
+int MyDataObj::count = 0;
+
+#include "SGTools/CLASS_DEF.h"
+CLASS_DEF(MyDataObj, 8000, 3) 
+
+#include <cassert>
+#include <vector>
+#include <map>
+
+#include "TestTools/initGaudi.h"
+
+//CLASSID_DEF(int, 34)
+//CLASSVERSION_DEF(int, 5)
+// CLASS_DEF(int, 8105, 1)
+// CLASS_DEF(std::vector<int>, 8002, 1)
+// CLASS_DEF2(std::map<int, float>, 8003, 1)
+CLASS_DEF(AbstractType, 8004, 1)
+CLASS_DEF(WrongType, 8005, 1)
+
+struct X1
+{
+  ~X1() {}
+  int a;
+};
+
+struct X2
+  : public virtual X1
+{
+  int b;
+};
+
+CLASS_DEF(X1, 8011, 1)
+CLASS_DEF(X2, 8012, 1)
+SG_BASE(X2, X1);
+
+CLASS_DEF( const int* , 206871866 , 1 )
+
+class X3
+{
+public:
+  int a;
+};
+CLASS_DEF(X3, 8013, 1)
+
+
+class XCopyConversion
+  : public SG::CopyConversion<X1, X3>
+{
+public:
+  void convert (const X1& src, X3& dst) const
+  { dst.a = src.a; }
+};
+
+SG_ADD_COPY_CONVERSION(X1, XCopyConversion);
+
+class X4
+{
+public:
+  int a;
+};
+CLASS_DEF(X4, 8014, 1)
+
+
+class X5
+{
+public:
+  X5 (int the_a) : a(the_a){}
+  ~X5() { log.push_back (a); }
+  int a;
+  static std::vector<int> log;
+};
+std::vector<int> X5::log;
+CLASS_DEF(X5, 8015, 1)
+
+
+class XLock : public ILockable
+{
+public:
+  XLock() : m_locked (false) {}
+  void lock() { m_locked = true; std::cout << "lock\n"; }
+  bool m_locked;
+};
+CLASS_DEF(XLock, 8114, 1)
+
+
+
+class TestRegisterTransient
+  : public IRegisterTransient
+{
+public:
+  virtual void registerTransient (void* trans) { m_xtrans.push_back (trans); }
+
+  std::vector<void*> m_xtrans;
+};
+
+
+
+// Test copying conversion.
+void test2()
+{
+  std::cout << "test2\n";
+  TestRegisterTransient trt;
+
+  X1* x1 = new X1;
+  x1->a = 10;
+  DataObject* xbucket = asStorable(x1);
+
+  const X3* x3 = Storable_cast<X3>(xbucket, false, &trt);
+  assert ((char*)x3 != (char*)x1);
+  assert (x3->a == 10);
+
+  assert (trt.m_xtrans.size() == 1);
+  assert (trt.m_xtrans[0] == x3);
+
+  const X4* x4 = Storable_cast<X4>(xbucket, true, &trt);
+  assert (x4 == 0);
+
+  assert (Storable_cast<X3>(xbucket, false, &trt, false) == 0);
+
+  SG::DataBucket<X1>* xb = dynamic_cast<SG::DataBucket<X1>*> (xbucket);
+  assert (xb->cast (ClassID_traits<X3>::ID(), &trt) == x3);
+  assert (xb->cast (typeid(X3), &trt) == x3);
+
+  assert (xb->cast (ClassID_traits<X4>::ID(), &trt) == 0);
+  assert (xb->cast (typeid(X4), &trt) == 0);
+
+  assert (xb->cast (ClassID_traits<X3>::ID(), &trt, false) == 0);
+  assert (xb->cast (typeid(X3), &trt, false) == 0);
+}
+
+
+// Test lock()
+void test3()
+{
+  std::cout << "test3\n";
+
+  X1* x1 = new X1;
+  XLock* xlock = new XLock;
+
+  DataObject* b1 = asStorable (x1);
+  DataObject* b2 = asStorable (xlock);
+
+  DataBucketBase* bb1 = dynamic_cast<DataBucketBase*> (b1);
+  DataBucketBase* bb2 = dynamic_cast<DataBucketBase*> (b2);
+
+  bb1->lock();
+  assert (!xlock->m_locked);
+  bb2->lock();
+  assert (xlock->m_locked);
+}
+
+
+int main () {
+  ISvcLocator* pDum;
+  Athena_test::initGaudi(pDum); //need the MessageSvc
+  assert( pDum );
+  DataBucket<int> intBucket(0);
+  DataBucket<const int*> pintBucket(0);
+  DataBucket<vector<int> > vintBucket(0);
+  cerr << "int has_classID " <<  intBucket.clID() << " version "
+       << ClassID_traits<int>::s_version << " and " 
+       << (ClassID_traits<int>::s_isDataObject ? "does" : "does not")
+       << " inherit from DataObject" <<endl;
+  cerr << "const int* has_classID " <<  pintBucket.clID() <<endl;
+  assert(intBucket.clID() == pintBucket.clID());
+
+  cerr << "vector<int> has_classID " <<  vintBucket.clID() <<endl;
+  DataBucket<GaudiDataObj> gdobjBucket(0);
+  cerr << "GaudiDataObj has_classID " <<  gdobjBucket.clID() << " and " 
+       << (ClassID_traits<GaudiDataObj>::s_isDataObject ? "does" : "does not")
+       << " inherit from DataObject" <<endl;
+  assert(gdobjBucket.clID() == GaudiDataObj::classID());
+  assert(ClassID_traits<GaudiDataObj>::s_isDataObject);
+
+  DataBucket<MyDataObj> dobjBucket(0);
+  cerr << "MyDataObj has_classID " <<  dobjBucket.clID() << " and " 
+       << (ClassID_traits<MyDataObj>::s_isDataObject ? "does" : "does not")
+       << " inherit from DataObject" <<endl;
+  assert(dobjBucket.clID() == ClassID_traits<MyDataObj>::ID());
+  assert(!ClassID_traits<MyDataObj>::s_isDataObject);
+
+  DataBucket<AbstractDataObj> absdobjBucket(0);
+  cerr << "AbstractDataObj has_classID " <<  absdobjBucket.clID() <<endl;
+  assert(absdobjBucket.clID() == AbstractDataObj::classID());
+  assert(ClassID_traits<AbstractDataObj>::s_isDataObject);
+
+  DataBucket<AbstractType> absBucket(0);
+  cerr << "AbstractType has_classID " <<  absBucket.clID() <<endl;
+  assert(absBucket.clID() == ClassID_traits<AbstractType>::ID());
+  assert(!ClassID_traits<AbstractType>::s_isDataObject);
+
+  assert("int" == ClassID_traits<int>::typeName());
+  assert("GaudiDataObj" == ClassID_traits<GaudiDataObj>::typeName());
+  if("std::map<int,float>" != 
+     ClassID_traits<map<int, float> >::typeName()) {
+    cerr << "error checking type name for map<int,float>: ClassID has it as " << ClassID_traits<map<int, float> >::typeName() <<endl;
+    assert(0);
+  }
+
+  MyDataObj* pMDO = new MyDataObj(1);
+  MyDataObj* pRes(0);
+
+  DataObject* pBucket(asStorable(pMDO));
+  assert(fromStorable(pBucket, pRes));
+  //FIXME asStorable above creates a DataBucket which is not deleted by anybody
+  WrongType* pWrong(0);
+  SGASSERTERROR(fromStorable(pBucket, pWrong));
+  assert(pMDO == pRes);
+  assert(pRes->val()==1);
+
+  pRes = 0;
+  //  static const bool QUIET(true);
+  static const bool VERBOSE(false);
+  assert(0 != (pRes = Storable_cast<MyDataObj>(pBucket, VERBOSE)));
+  
+  cerr << "Now we expect to see an error message:" << endl 
+	    << "----Error Message Starts--->>" << endl; 
+  pWrong = Storable_cast<WrongType>(pBucket, VERBOSE);
+  assert(0 == pWrong);
+  cerr<< "<<---Error Message Ends-------" << endl;
+  cerr << "Now we expect to see an error message:" << endl 
+	    << "----Error Message Starts--->>" << endl; 
+  pWrong = Storable_cast<WrongType>((DataObject*)0);
+  assert(0 == pWrong);
+  cerr<< "<<---Error Message Ends-------" << endl;
+  delete pBucket;
+	 
+  GaudiDataObj* pGDO = new GaudiDataObj(2);
+  GaudiDataObj* pGRes(0);
+  DataObject* DBGDO(asStorable(pGDO));
+  assert(fromStorable(DBGDO, pGRes));
+  SGASSERTERROR(fromStorable(DBGDO, pWrong));
+  assert(pGDO == pGRes);
+  assert(pGRes->val()==2);
+
+  DataObject* pDO(0);
+  assert (0 != (pDO = asStorable(new GaudiDataObj(3))));
+  pGRes = 0;
+  assert(0 != (pGRes = Storable_cast<GaudiDataObj>(pDO, VERBOSE)));
+
+  const DataObject& rDO(*pDO);
+  const GaudiDataObj& rGRes(Storable_cast<GaudiDataObj>(rDO, VERBOSE));
+  
+  try {
+    cerr << "Now we expect to see an error message:" << endl 
+              << "----Error Message Starts--->>" << endl; 
+    const WrongType& rWr = Storable_cast<WrongType>(rGRes, VERBOSE);
+    pWrong=const_cast<WrongType*>(&rWr); //remove warning
+  } catch (bad_Storable_cast ) {
+    cerr << "<<---Error Message Ends-------" << endl;
+  }
+
+  const DataObject* cpDO(pDO);
+  const GaudiDataObj* cpGRes(Storable_cast<GaudiDataObj>(cpDO, VERBOSE));
+  assert( 0 != cpGRes );
+  delete pDO;
+  delete DBGDO;
+
+  //----------------------------------------------------------
+  X2* x2 = new X2;
+  X1* x1 = x2;
+  assert ((long)x1 != (long)x2);
+  DataObject* xbucket = asStorable(x2);
+  X1* x1b = 0;
+  assert (fromStorable (xbucket, x1b));
+  assert (x1 == x1b);
+  delete xbucket;
+  //----------------------------------------------------------
+  // Test refcounting.
+  int c1 = GaudiDataObj::count;
+  int c2 = MyDataObj::count;
+  GaudiDataObj* gdo = new GaudiDataObj;
+  assert(1 == gdo->addRef());
+  DataBucketBase* b1 = dynamic_cast<DataBucketBase*>(asStorable(gdo));
+  assert(1 == b1->addRef());
+  assert(1 == b1->refCount());
+  assert(2 == gdo->refCount());  //notice how DB and DO have indep refcounts
+  assert(1 == gdo->release());
+  assert(1 == gdo->refCount());
+  assert(1 == b1->refCount());
+  assert(0 == b1->release());
+  assert (c1 == GaudiDataObj::count);
+  //another combination
+  gdo = new GaudiDataObj;
+  assert(1 == gdo->addRef());
+  DataObject* b2(asStorable(gdo));
+  assert(3 == gdo->addRef());
+  delete b2; //this must not delete gdo, only decrease its refcount
+  assert(2 == gdo->refCount()); 
+  assert (c1 + 1 == GaudiDataObj::count);
+  //this is simpler: no DataObj in play
+  b2 = asStorable(new MyDataObj);
+  delete b2;
+  assert (c2 == MyDataObj::count);
+  //cleanup
+  delete gdo;
+  //----------------------------------------------------------
+
+#if __cplusplus > 201100
+  {
+    std::unique_ptr<X5> p (new X5(10));
+    DataBucketBase* b3 = new DataBucket<X5> (std::move(p));
+    assert (p.get() == 0);
+    assert (X5::log.empty());
+    delete b3;
+    assert (X5::log == std::vector<int> {10});
+    X5::log.clear();
+  }
+
+  {
+    std::unique_ptr<X5> p (new X5(11));
+    DataObject* b4 = asStorable (std::move(p));
+    assert (p.get() == 0);
+    assert (X5::log.empty());
+    delete b4;
+    assert (X5::log == std::vector<int> {11});
+  }
+#endif
+
+  test2();
+  test3();
+
+  cerr << "*** DataBucket_test OK ***" <<endl;
+  return 0;
+
+}
+
+
diff --git a/Control/SGTools/test/DataProxy_test.cxx b/Control/SGTools/test/DataProxy_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..71de6e5829ceae0230011fab6f00790e8f77e3ab
--- /dev/null
+++ b/Control/SGTools/test/DataProxy_test.cxx
@@ -0,0 +1,133 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file DataProxy_test.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Nov, 2013
+ * @brief Regression tests for DataProxy.
+ */
+
+#undef NDEBUG
+#include "SGTools/DataProxy.h"
+#include "SGTools/IProxyDictWithPool.h"
+#include "SGTools/StorableConversions.h"
+#include "SGTools/CLASS_DEF.h"
+#include "AthenaKernel/ILockable.h"
+#include <iostream>
+#include <cstdlib>
+#include <cassert>
+
+
+struct X1
+{
+  ~X1() {}
+};
+CLASS_DEF(X1, 8011, 1)
+
+class XLock : public ILockable
+{
+public:
+  XLock() : m_locked (false) {}
+  void lock() { m_locked = true; std::cout << "lock\n"; }
+  bool m_locked;
+};
+CLASS_DEF(XLock, 8114, 1)
+
+class TestStore
+  : public IProxyDictWithPool
+{
+public:
+  unsigned long addRef()
+  { std::cout << "addRef\n"; std::abort(); }
+  unsigned long release()
+  { std::cout << "release\n"; std::abort(); }
+  StatusCode queryInterface(const InterfaceID &/*ti*/, void** /*pp*/)
+  { std::cout << "queryInterface\n"; std::abort(); }
+  const std::string& name() const
+  { std::cout << "name\n"; std::abort(); }
+
+
+  SG::DataProxy* deep_proxy(const void* const /*pTransient*/) const
+  { std::cout << "deep_proxy\n"; std::abort(); }
+  SG::DataProxy* proxy(const void* const /*pTransient*/) const
+  { std::cout << "proxy1\n"; std::abort(); }
+  SG::DataProxy* proxy(const CLID& /*id*/) const
+  { std::cout << "proxy2\n"; std::abort(); }
+  SG::DataProxy* proxy(const CLID& /*id*/, const std::string& /*key*/) const
+  { std::cout << "proxy3\n"; std::abort(); }
+  SG::DataProxy* proxy_exact (SG::sgkey_t /*sgkey*/) const
+  { std::cout << "proxy_exact1\n"; std::abort(); }
+  std::vector<const SG::DataProxy*> proxies() const
+  { std::cout << "proxies\n"; std::abort(); }
+  StatusCode addToStore (CLID /*id*/, SG::DataProxy* /*proxy*/)
+  { std::cout << "addToStore\n";  std::abort(); }
+
+  sgkey_t stringToKey (const std::string& /*str*/, CLID /*clid*/)
+  { std::cout << "stringToKey\n"; std::abort(); }
+  const std::string* keyToString (sgkey_t /*key*/) const
+  { std::cout << "keyToString1\n"; std::abort(); }
+  const std::string* keyToString (sgkey_t /*key*/, CLID& /*clid*/) const
+  { std::cout << "keyToString2\n"; std::abort(); }
+  void registerKey (sgkey_t /*key*/, const std::string& /*str*/, CLID /*clid*/)
+  { std::cout << "registerKey\n"; std::abort(); }
+};
+
+
+void test1()
+{
+  std::cout << "test1\n";
+  TestStore store;
+
+  SG::DataProxy dp;
+  assert (dp.store() == 0);
+  dp.setStore (&store);
+  assert (dp.store() == &store);
+}
+
+
+// Test setConst()
+void test2()
+{
+  std::cout << "test2\n";
+
+  X1* x1 = new X1;
+  DataObject* b1 = SG::asStorable (x1);
+  SG::DataProxy dp1;
+  dp1.setObject (b1);
+  assert (!dp1.isConst());
+  dp1.setConst();
+  assert (dp1.isConst());
+
+  XLock* xlock = new XLock;
+  DataObject* b2 = SG::asStorable (xlock);
+  SG::DataProxy dp2;
+  dp2.setObject (b2);
+  assert (!dp2.isConst());
+  assert (!xlock->m_locked);
+  dp2.setConst();
+  assert (dp2.isConst());
+  assert (xlock->m_locked);
+
+  XLock* xlock_a = new XLock;
+  DataObject* b2a = SG::asStorable (xlock_a);
+  assert (!xlock_a->m_locked);
+  dp2.setObject (b2a);
+  assert (xlock_a->m_locked);
+  assert (dp2.isConst());
+}
+
+
+int main()
+{
+  test1();
+  test2();
+
+  // FIXME: INCOMPLETE!
+
+  return 0;
+}
+
+
diff --git a/Control/SGTools/test/DataStore_test.cxx b/Control/SGTools/test/DataStore_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..4a1aa8df79927f8d01ed14f9df6a052bfdf8c58d
--- /dev/null
+++ b/Control/SGTools/test/DataStore_test.cxx
@@ -0,0 +1,573 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file DataStore_test.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Nov, 2013
+ * @brief Regression tests for DataStore.
+ */
+
+#undef NDEBUG
+#include "SGTools/DataStore.h"
+#include "SGTools/StringPool.h"
+#include "SGTools/DataProxy.h"
+#include "SGTools/TransientAddress.h"
+#include "SGTools/IProxyDictWithPool.h"
+#include "AthenaKernel/getMessageSvc.h"
+#include "AthenaKernel/IAddressProvider.h"
+#include <iostream>
+#include <cstdlib>
+#include <cassert>
+
+
+class TestProvider
+  : public IAddressProvider
+{
+public:
+  virtual StatusCode updateAddress(StoreID::type /*storeID*/,
+				   SG::TransientAddress* /*pTAd*/)
+  { return StatusCode::SUCCESS; }
+};
+
+
+class TestPool
+  : public IProxyDictWithPool
+{
+public:
+  virtual
+  sgkey_t stringToKey (const std::string& str, CLID clid)
+  { return m_pool.stringToKey (str, clid); }
+  virtual
+  const std::string* keyToString (sgkey_t key) const 
+  { return m_pool.keyToString (key); }
+  virtual
+  const std::string* keyToString (sgkey_t key,
+                                  CLID& clid) const
+  { return m_pool.keyToString (key, clid); }
+  virtual
+  void registerKey (sgkey_t key,
+                    const std::string& str,
+                    CLID clid)
+  { m_pool.registerKey (key, str, clid); }
+
+
+  virtual unsigned long addRef() { std::abort(); }
+  virtual unsigned long release() { std::abort(); }
+  virtual const std::string& name() const { std::abort(); }
+  virtual StatusCode queryInterface(const InterfaceID &, void** )  { std::abort(); }
+  virtual SG::DataProxy* proxy(const CLID&) const { std::abort(); }
+  virtual StatusCode addToStore (CLID , SG::DataProxy*) { std::abort(); }
+  virtual SG::DataProxy* deep_proxy(const void* const) const { std::abort(); }
+  virtual SG::DataProxy* proxy(const void* const) const { std::abort(); }
+  virtual SG::DataProxy* proxy_exact (SG::sgkey_t) const { std::abort(); }
+  virtual std::vector<const SG::DataProxy*> proxies() const { std::abort(); }
+  virtual SG::DataProxy* proxy(const CLID&, const std::string&) const { std::abort(); }
+
+  SG::StringPool m_pool;
+};
+
+
+SG::DataProxy* make_proxy (CLID clid, const std::string& name)
+{
+  SG::TransientAddress* tad = new SG::TransientAddress (clid, name);
+  return new SG::DataProxy (tad, (IConversionSvc*)0);
+}
+
+
+void test_ctor()
+{
+  std::cout << "test_ctor\n";
+  TestPool pool;
+  SG::DataStore store (pool);
+  assert (store.storeID() == StoreID::UNKNOWN);
+  store.setStoreID (StoreID::SPARE_STORE);
+  assert (store.storeID() == StoreID::SPARE_STORE);
+}
+
+
+void test_addToStore()
+{
+  std::cout << "test_addToStore\n";
+
+  TestPool pool;
+  SG::DataStore store (pool);
+  SG::StringPool::sgkey_t sgkey = pool.stringToKey ("dp1", 123);
+
+  assert (store.addToStore (123, 0).isFailure());
+  SG::DataProxy* dp1 = make_proxy (123, "dp1");
+  assert (dp1->refCount() == 0);
+  assert (store.addToStore (123, dp1).isSuccess());
+  assert (dp1->store() == &pool);
+  assert (dp1->refCount() == 1);
+  assert (dp1->transientAddress()->sgkey() == sgkey);
+  assert (store.proxy_exact (sgkey) == dp1);
+  assert (store.proxy (123, "dp1") == dp1);
+
+  int trans1;
+  dp1->registerTransient (&trans1);
+  assert (store.locatePersistent (&trans1) == dp1);
+
+  SG::DataProxy* dp2 = make_proxy (123, "dp2");
+  assert (store.addToStore (124, dp2).isSuccess());
+  SG::StringPool::sgkey_t sgkey2a = pool.stringToKey ("dp2", 123);
+  SG::StringPool::sgkey_t sgkey2b = pool.stringToKey ("dp2", 124);
+  assert (store.proxy_exact (sgkey2b) == dp2);
+  assert (store.proxy_exact (sgkey2a) == 0);
+  assert (dp2->transientAddress()->sgkey() == sgkey2a);
+}
+
+
+void test_addAlias()
+{
+  std::cout << "test_addAlias\n";
+
+  TestPool pool;
+  SG::DataStore store (pool);
+
+  SG::DataProxy* dp1 = make_proxy (123, "dp1");
+  assert (store.addToStore (123, dp1).isSuccess());
+
+  assert (store.addAlias ("dp1a", dp1).isSuccess());
+  assert (store.addAlias ("dp1b", dp1).isSuccess());
+  assert (dp1->refCount() == 3);
+
+  assert (store.proxy (123, "dp1a") == dp1);
+  assert (store.proxy_exact (pool.stringToKey ("dp1a", 123)) == dp1);
+
+  assert (dp1->transientAddress()->alias().count ("dp1a") == 1);
+
+  SG::DataProxy* dp2 = make_proxy (123, "dp2");
+  assert (store.addToStore (123, dp2).isSuccess());
+  assert (store.addAlias ("dpx", dp2).isSuccess());
+  assert (dp2->refCount() == 2);
+  assert (dp2->transientAddress()->alias().count ("dpx") == 1);
+
+  assert (store.addAlias ("dpx", dp1).isSuccess());
+  assert (dp1->refCount() == 4);
+  assert (dp2->refCount() == 1);
+  assert (dp2->transientAddress()->alias().count ("dpx") == 0);
+  assert (dp1->transientAddress()->alias().count ("dpx") == 1);
+  assert (store.addAlias ("dpx", dp1).isSuccess());
+  assert (dp1->refCount() == 4);
+  assert (dp2->refCount() == 1);
+}
+
+
+void test_addSymLink()
+{
+  std::cout << "test_addSymLink\n";
+
+  TestPool pool;
+  SG::DataStore store (pool);
+
+  SG::DataProxy* dp1 = make_proxy (123, "dp1");
+  assert (store.addToStore (123, dp1).isSuccess());
+  assert (store.addSymLink (124, dp1).isSuccess());
+
+  assert (store.proxy_exact (123, "dp1") == dp1);
+  assert (store.proxy_exact (124, "dp1") == dp1);
+  assert (dp1->transientAddress()->transientID(123));
+  assert (dp1->transientAddress()->transientID(124));
+
+  assert (store.addSymLink (124, dp1).isSuccess());
+  assert (store.proxy_exact (124, "dp1") == dp1);
+
+  SG::DataProxy* dp2 = make_proxy (125, "dp1");
+  assert (store.addToStore (125, dp2).isSuccess());
+  assert (store.addSymLink (125, dp1).isFailure());
+  assert (!dp1->transientAddress()->transientID(125));
+}
+
+
+void test_proxy_exact()
+{
+  std::cout << "test_proxy_exact\n";
+
+  TestPool pool;
+  SG::DataStore store (pool);
+
+  SG::DataProxy* dp1 = make_proxy (123, "dp1");
+  assert (store.addToStore (123, dp1).isSuccess());
+
+  assert (store.proxy_exact (123, "dp1") == dp1);
+  assert (store.proxy_exact (124, "dp1") == 0);
+  assert (store.proxy_exact (123, "dp2") == 0);
+  SG::StringPool::sgkey_t sgkey = pool.stringToKey ("dp1", 123);
+  assert (store.proxy_exact (sgkey) == dp1);
+  assert (store.proxy_exact (sgkey+1) == 0);
+}
+
+
+void test_proxy()
+{
+  std::cout << "test_proxy\n";
+
+  TestPool pool;
+  SG::DataStore store (pool);
+
+  SG::DataProxy* dp1 = make_proxy (123, "dp1");
+  assert (store.addToStore (123, dp1).isSuccess());
+
+  assert (store.proxy (123, "dp1") == dp1);
+  assert (store.proxy (123, "") == dp1);
+
+  assert (store.proxy (new SG::TransientAddress (123, "dp1")) == dp1);
+
+  assert (store.addAlias ("dp1a", dp1).isSuccess());
+  assert (store.addAlias ("dp1b", dp1).isSuccess());
+  assert (store.proxy (123, "") == dp1);
+
+  SG::DataProxy* dp2 = make_proxy (124, "dp2");
+  assert (store.addToStore (123, dp2).isSuccess());
+  assert (store.proxy (123, "") == dp1);
+
+  SG::DataProxy* dp3 = make_proxy (123, "dp3");
+  assert (store.addToStore (123, dp3).isSuccess());
+  assert (store.proxy (123, "") == 0);
+  assert (store.proxy (123, "dp3") == dp3);
+}
+
+
+void test_typeCount()
+{
+  std::cout << "test_typeCount\n";
+
+  TestPool pool;
+  SG::DataStore store (pool);
+
+  SG::DataProxy* dp1 = make_proxy (123, "dp1");
+  assert (store.addToStore (123, dp1).isSuccess());
+  assert (store.addSymLink (124, dp1).isSuccess());
+
+  SG::DataProxy* dp2 = make_proxy (123, "dp2");
+  assert (store.addToStore (123, dp2).isSuccess());
+
+  assert (store.typeCount (123) == 2);
+  assert (store.typeCount (124) == 1);
+  assert (store.typeCount (125) == 0);
+}
+
+
+void test_tRange()
+{
+  std::cout << "test_tRange\n";
+
+  TestPool pool;
+  SG::DataStore store (pool);
+
+  SG::DataProxy* dp1 = make_proxy (123, "dp1");
+  assert (store.addToStore (123, dp1).isSuccess());
+  assert (store.addSymLink (124, dp1).isSuccess());
+
+  SG::DataProxy* dp2 = make_proxy (123, "dp2");
+  assert (store.addToStore (123, dp2).isSuccess());
+
+  SG::DataStore::ConstStoreIterator tbeg;
+  SG::DataStore::ConstStoreIterator tend;
+  assert (store.tRange (tbeg, tend).isSuccess());
+
+  assert (tbeg->first == 123);
+  assert (tbeg->second.size() == 2);
+  ++tbeg;
+  assert (tbeg->first == 124);
+  assert (tbeg->second.size() == 1);
+  ++tbeg;
+  assert (tbeg == tend);
+}
+
+
+void test_pRange()
+{
+  std::cout << "test_pRange\n";
+
+  TestPool pool;
+  SG::DataStore store (pool);
+
+  SG::DataProxy* dp1 = make_proxy (123, "dp1");
+  assert (store.addToStore (123, dp1).isSuccess());
+  assert (store.addSymLink (124, dp1).isSuccess());
+
+  SG::DataProxy* dp2 = make_proxy (123, "dp2");
+  assert (store.addToStore (123, dp2).isSuccess());
+
+  SG::ConstProxyIterator pbeg;
+  SG::ConstProxyIterator pend;
+
+  assert (store.pRange (123, pbeg, pend).isSuccess());
+  assert (pbeg->first == "dp1");
+  assert (pbeg->second == dp1);
+  ++pbeg;
+  assert (pbeg->first == "dp2");
+  assert (pbeg->second == dp2);
+  ++pbeg;
+  assert (pbeg == pend);
+
+  assert (store.pRange (124, pbeg, pend).isSuccess());
+  assert (pbeg->first == "dp1");
+  assert (pbeg->second == dp1);
+  ++pbeg;
+  assert (pbeg == pend);
+
+  assert (store.pRange (125, pbeg, pend).isFailure());
+  assert (pbeg == pend);
+}
+
+
+void test_proxyList()
+{
+  std::cout << "test_proxyList\n";
+
+  TestPool pool;
+  SG::DataStore store (pool);
+
+  SG::DataProxy* dp1 = make_proxy (123, "dp1");
+  assert (store.addToStore (123, dp1).isSuccess());
+  assert (store.addSymLink (124, dp1).isSuccess());
+
+  SG::DataProxy* dp2 = make_proxy (123, "dp2");
+  assert (store.addToStore (123, dp2).isSuccess());
+
+  std::list<SG::DataProxy*> pl;
+  assert (store.proxyList (pl).isSuccess());
+  assert (pl.size() == 3);
+
+  std::vector<SG::DataProxy*> pv (pl.begin(), pl.end());
+  assert (pv[0] == dp1);
+  assert (pv[1] == dp2);
+  assert (pv[2] == dp1);
+}
+
+
+void test_keys()
+{
+  std::cout << "test_keys\n";
+
+  TestPool pool;
+  SG::DataStore store (pool);
+
+  SG::DataProxy* dp1 = make_proxy (123, "dp1");
+  assert (store.addToStore (123, dp1).isSuccess());
+  assert (store.addSymLink (124, dp1).isSuccess());
+
+  SG::DataProxy* dp2 = make_proxy (123, "dp2");
+  assert (store.addToStore (123, dp2).isSuccess());
+
+  std::vector<std::string> v;
+  store.keys (123, v, true, false);
+  assert (v.size() == 2);
+  assert (v[0] == "dp1");
+  assert (v[1] == "dp2");
+
+  store.keys (124, v, true, false);
+  assert (v.size() == 1);
+  assert (v[0] == "dp1");
+
+  assert (store.addAlias ("dp1a", dp1).isSuccess());
+  store.keys (123, v, false, false);
+  assert (v.size() == 2);
+  assert (v[0] == "dp1");
+  assert (v[1] == "dp2");
+
+  store.keys (123, v, true, false);
+  assert (v.size() == 3);
+  assert (v[0] == "dp1");
+  assert (v[1] == "dp1a");
+  assert (v[2] == "dp2");
+
+  SG::DataProxy* dp3 = make_proxy (125, "dp3");
+  SG::DataProxy* dp4 = make_proxy (125, "dp4");
+  assert (store.addToStore (125, dp3).isSuccess());
+  assert (store.addToStore (125, dp4).isSuccess());
+  TestProvider prov;
+  dp4->transientAddress()->setProvider (&prov, StoreID::SPARE_STORE);
+
+  store.keys (125, v, true, false);
+  assert (v.size() == 2);
+  assert (v[0] == "dp3");
+  assert (v[1] == "dp4");
+
+  store.keys (125, v, true, true);
+  assert (v.size() == 1);
+  assert (v[0] == "dp4");
+}
+
+
+void test_removeProxy()
+{
+  std::cout << "test_removeProxy\n";
+
+  TestPool pool;
+  SG::DataStore store (pool);
+
+  assert (store.removeProxy (0, false).isFailure());
+
+  SG::DataProxy* dp1 = make_proxy (123, "dp1");
+  dp1->addRef();
+  assert (store.addToStore (123, dp1).isSuccess());
+  assert (store.addSymLink (124, dp1).isSuccess());
+  assert (store.addAlias ("dp1x", dp1).isSuccess());
+
+  assert (store.proxy_exact (pool.stringToKey ("dp1", 123)) == dp1);
+  assert (store.proxy_exact (pool.stringToKey ("dp1", 124)) == dp1);
+  assert (store.proxy_exact (pool.stringToKey ("dp1x", 123)) == dp1);
+  assert (store.proxy (123, "dp1") == dp1);
+  assert (store.proxy (124, "dp1") == dp1);
+  assert (store.proxy (123, "dp1x") == dp1);
+
+  assert (dp1->refCount() == 4);
+
+  dp1->resetOnly (true);
+  assert (store.removeProxy (dp1, false).isSuccess());
+  assert (dp1->refCount() == 4);
+
+  dp1->resetOnly (false);
+  assert (store.removeProxy (dp1, false).isSuccess());
+  assert (dp1->refCount() == 1);
+  assert (store.proxy_exact (pool.stringToKey ("dp1", 123)) == 0);
+  assert (store.proxy_exact (pool.stringToKey ("dp1", 124)) == 0);
+  assert (store.proxy_exact (pool.stringToKey ("dp1x", 123)) == 0);
+  assert (store.proxy (123, "dp1") == 0);
+  assert (store.proxy (124, "dp1") == 0);
+  assert (store.proxy (123, "dp1x") == 0);
+
+}
+
+
+void test_clearStore()
+{
+  std::cout << "test_clearStore\n";
+
+  TestPool pool;
+  SG::DataStore store (pool);
+
+  SG::DataProxy* dp1 = make_proxy (123, "dp1");
+  DataObject* o1 = new DataObject;
+  dp1->setObject (o1);
+  dp1->addRef();
+  assert (store.addToStore (123, dp1).isSuccess());
+  assert (store.addSymLink (124, dp1).isSuccess());
+  dp1->resetOnly (false);
+
+  SG::DataProxy* dp2 = make_proxy (123, "dp2");
+  assert (store.addToStore (123, dp2).isSuccess());
+  DataObject* o2 = new DataObject;
+  dp2->setObject (o2);
+  dp2->addRef();
+
+  assert (dp1->refCount() == 3);
+  assert (dp2->refCount() == 2);
+
+  int trans1;
+  dp1->registerTransient (&trans1);
+  assert (store.locatePersistent (&trans1) == dp1);
+  int trans2;
+  dp2->registerTransient (&trans2);
+  assert (store.locatePersistent (&trans2) == dp2);
+
+  store.clearStore();
+
+  assert (store.locatePersistent (&trans1) == 0);
+  assert (store.locatePersistent (&trans2) == 0);
+
+  assert (dp1->refCount() == 1);
+  assert (dp1->object() == o1);
+  assert (store.proxy (123, "dp1") == 0);
+  assert (store.proxy (124, "dp1") == 0);
+  assert (store.proxy_exact (pool.stringToKey ("dp1", 123)) == 0);
+  assert (store.proxy_exact (pool.stringToKey ("dp1", 124)) == 0);
+
+  assert (dp2->refCount() == 2);
+  assert (dp2->object() == 0);
+  assert (store.proxy (123, "dp2") == dp2);
+  assert (store.proxy_exact (pool.stringToKey ("dp2", 123)) == dp2);
+
+  store.clearStore(true);
+  assert (dp2->refCount() == 1);
+  assert (store.proxy (123, "dp2") == 0);
+  assert (store.proxy_exact (pool.stringToKey ("dp2", 123)) == 0);
+}
+
+
+void test_t2p()
+{
+  std::cout << "test_t2p\n";
+
+  TestPool pool;
+  SG::DataStore store (pool);
+
+  SG::DataProxy* dp1 = make_proxy (123, "dp1");
+  assert (store.addToStore (123, dp1).isSuccess());
+
+  int trans1;
+  assert (store.locatePersistent (&trans1) == 0);
+  assert (store.t2pRegister (&trans1, dp1).isSuccess());
+  assert (store.locatePersistent (&trans1) == dp1);
+  assert (store.locatePersistent (&trans1) == dp1);
+  assert (store.t2pRegister (&trans1, dp1).isFailure());
+  store.t2pRemove (&trans1);
+  assert (store.locatePersistent (&trans1) == 0);
+}
+
+
+void test_dummy()
+{
+  std::cout << "test_dummy\n";
+
+  TestPool pool;
+  SG::DataStore store (pool);
+
+  SG::StringPool::sgkey_t sgkey = pool.stringToKey ("dp1", 456);
+
+  SG::DataProxy* dp1 = make_proxy (0, "");
+  dp1->transientAddress()->setSGKey (sgkey);
+  assert (store.addToStore (0, dp1).isSuccess());
+  assert (dp1->refCount() == 1);
+  assert (store.proxy_exact (sgkey) == dp1);
+
+  assert (store.proxy (456, "dp1") == dp1);
+  assert (dp1->clID() == 456);
+  assert (dp1->name() == "dp1");
+  assert (dp1->refCount() == 1);
+
+  SG::StringPool::sgkey_t sgkey2 = pool.stringToKey ("dp2", 456);
+  SG::DataProxy* dp2 = make_proxy (0, "");
+  dp2->transientAddress()->setSGKey (sgkey2);
+  assert (store.addToStore (0, dp2).isSuccess());
+  assert (dp2->refCount() == 1);
+  assert (store.proxy_exact (sgkey2) == dp2);
+
+  assert (store.proxy (456, "dp2") == dp2);
+  assert (dp2->clID() == 456);
+  assert (dp2->name() == "dp2");
+  assert (dp2->refCount() == 1);
+}
+
+
+int main()
+{
+  Athena::getMessageSvcQuiet = true;
+  test_ctor();
+  test_addToStore();
+  test_addAlias();
+  test_addSymLink();
+  test_proxy_exact();
+  test_proxy();
+  test_typeCount();
+  test_tRange();
+  test_pRange();
+  test_proxyList();
+  test_keys();
+  test_removeProxy();
+  test_clearStore();
+  test_t2p();
+  // pac routines not tested.
+  test_dummy();
+  return 0;
+}
+
+
+// handle retrieval of dummied dp
+// insert dummied dp
diff --git a/Control/SGTools/test/SGTools.xml b/Control/SGTools/test/SGTools.xml
new file mode 100755
index 0000000000000000000000000000000000000000..cf2d08d1d457c5a83d86225f56d2f7b7a7af6c40
--- /dev/null
+++ b/Control/SGTools/test/SGTools.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<atn>
+    <TEST name="SGToolsTest" type="makecheck" suite="Examples">
+       <package>Control/SGTools</package>
+       <timelimit>10</timelimit>
+       <author> Paolo Calafiura </author>
+       <mailto> pcalafiura@lbl.gov</mailto>
+       <expectations>
+          <errorMessage>Athena exited abnormally</errorMessage>
+          <errorMessage>differ</errorMessage>
+          <warningMessage> # WARNING_MESSAGE : post.sh> ERROR</warningMessage>
+          <successMessage>check ok</successMessage>
+          <returnValue>0</returnValue>
+       </expectations>
+    </TEST>
+</atn>
diff --git a/Control/SGTools/test/StringPool_test.cxx b/Control/SGTools/test/StringPool_test.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..796666ba91ac9a8348e603c31d1529f51192b9b1
--- /dev/null
+++ b/Control/SGTools/test/StringPool_test.cxx
@@ -0,0 +1,105 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: StringPool_test.cxx,v 1.2 2007-12-10 22:20:04 ssnyder Exp $
+/**
+ * @file  SGTools/StringPool_test.cxx
+ * @author scott snyder
+ * @date Mar 2007
+ * @brief Regression test for StringPool.
+ */
+
+
+#undef NDEBUG
+
+#include "SGTools/StringPool.h"
+#include "SGTools/crc64.h"
+#include <vector>
+#include <string>
+#include <cstdlib>
+#include <cassert>
+#include <iostream>
+
+
+const char* teststrings[] = {
+  "",
+  "MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE",
+  "MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE",
+  "ajsdla lkjasd lkjasd ",
+  "paks  aspdk pok  asd",
+  "asd  laskjkd lkajsd",
+};
+
+
+std::string randstring()
+{
+  char buf[256];
+  int len = std::rand() % 256;
+  for (int i = 0; i < len; i++)
+    buf[i] = (char)(std::rand() % 256);
+  return std::string (buf, len);
+}
+
+
+void test1()
+{
+  SG::StringPool sp;
+  std::vector<std::string> strings;
+  std::vector<SG::StringPool::sgkey_t> keys;
+  std::vector<SG::StringPool::sgaux_t> aux;
+  int ntest = sizeof (teststrings) / sizeof (teststrings[0]);
+  for (int i = 0; i < ntest; i++) {
+    SG::StringPool::sgkey_t key = sp.stringToKey (teststrings[i], i);
+    assert (key <= SG::StringPool::sgkey_t_max);
+    strings.push_back (teststrings[i]);
+    keys.push_back (key);
+    aux.push_back (i);
+    std::cout << SG::crc64format (key) << " " << teststrings[i] << "\n";
+  }
+
+  std::cout << "pool dump\n";
+  sp.dump();
+
+  for (int i=0; i < 1000; i++) {
+    SG::StringPool::sgaux_t auxkey = std::rand();
+    std::string str = randstring();
+    SG::StringPool::sgkey_t key = sp.stringToKey (str, auxkey);
+    assert (key <= SG::StringPool::sgkey_t_max);
+    strings.push_back (str);
+    keys.push_back (key);
+    aux.push_back (auxkey);
+  }
+
+  for (size_t i = 0; i < keys.size(); i++) {
+    SG::StringPool::sgaux_t auxout;
+    assert (*sp.keyToString (keys[i]) == strings[i]);
+    assert (*sp.keyToString (keys[i], auxout) == strings[i]);
+    assert (auxout == aux[i]);
+    assert (!sp.keyToString (keys[i]+1));
+  }
+
+  for (size_t i = 0; i < keys.size(); i++) {
+    assert (sp.registerKey (keys[i]+1, strings[i], aux[i]));
+  }
+
+  for (size_t i = 0; i < keys.size(); i++) {
+    SG::StringPool::sgaux_t auxout = 0;
+    assert (*sp.keyToString (keys[i], auxout) == strings[i]);
+    assert (auxout == aux[i]);
+    auxout = 0;
+    assert (*sp.keyToString (keys[i]+1, auxout) == strings[i]);
+    assert (auxout == aux[i]);
+  }
+
+  assert (sp.registerKey (keys[10], strings[10], aux[10]));
+  assert (!sp.registerKey (keys[10], strings[11], aux[10]));
+  assert (!sp.registerKey (keys[10], strings[10], aux[11]));
+}
+
+
+int main()
+{
+  test1();
+  return 0;
+}
diff --git a/Control/SGTools/test/TransientAddress_test.cxx b/Control/SGTools/test/TransientAddress_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..3a58bbb610477ebdf37beaad415af2af906093ed
--- /dev/null
+++ b/Control/SGTools/test/TransientAddress_test.cxx
@@ -0,0 +1,181 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file TransientAddress_test.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Nov, 2013
+ * @brief Regression tests for TransientAddress.
+ */
+
+#undef NDEBUG
+#include "SGTools/TransientAddress.h"
+#include "AthenaKernel/IAddressProvider.h"
+#include "GaudiKernel/IOpaqueAddress.h"
+#include <iostream>
+#include <cstdlib>
+#include <cassert>
+
+
+class TestAddress
+  : public IOpaqueAddress
+{
+public:
+  TestAddress (int x) : m_x (x), m_ref(0) {}
+  /// Add reference to object
+  virtual unsigned long        addRef     ();
+  /// release reference to object
+  virtual unsigned long        release    ();
+  /// Retrieve class information from link
+  virtual const CLID&          clID       () const { std::abort(); }
+  /// Retrieve service type
+  virtual long                 svcType    () const { std::abort(); }
+  /// Update branch name
+  virtual IRegistry*           registry   () const { std::abort(); }
+  /// Update directory pointer
+  virtual void                 setRegistry(IRegistry* /*r*/) { std::abort(); }
+  /// Retrieve String parameters
+  virtual const std::string*   par        () const { std::abort(); }
+  /// Access to generic link parameters
+  virtual const unsigned long* ipar       () const { std::abort(); }
+
+  int m_x;
+  int m_ref;
+};
+
+
+class TestProvider
+  : public IAddressProvider
+{
+public:
+  virtual StatusCode updateAddress(StoreID::type /*storeID*/,
+				   SG::TransientAddress* /*pTAd*/)
+  { return StatusCode::SUCCESS; }
+};
+
+
+unsigned long TestAddress::addRef()
+{
+  ++m_ref;
+  std::cout << "addRef " << m_x << " " << m_ref << "\n";
+  return m_ref;
+}
+
+
+unsigned long TestAddress::release()
+{
+  --m_ref;
+  std::cout << "release " << m_x << " " << m_ref << "\n";
+  return m_ref;
+}
+
+
+void test1()
+{
+  std::cout << "test1\n";
+
+  SG::TransientAddress tad1;
+  assert (tad1.clID() == CLID_NULL);
+  assert (tad1.name() == "");
+  assert (tad1.transientID().size() == 0);
+  assert (tad1.alias().size() == 0);
+  assert (!tad1.isValid());
+  assert (tad1.provider() == 0);
+  assert (tad1.storeID() == StoreID::UNKNOWN);
+  assert (tad1.address() == 0);
+  assert (tad1.sgkey() == 0);
+  tad1.setID (123, "key");
+  assert (tad1.name() == "key");
+  assert (tad1.clID() == 123);
+  assert (tad1.transientID().size() == 1);
+  assert (tad1.alias().size() == 0);
+
+  SG::TransientAddress tad2 (123, "key");
+  assert (tad2.name() == "key");
+  assert (tad2.clID() == 123);
+  assert (tad2.transientID().size() == 1);
+  assert (tad2.alias().size() == 0);
+  assert (!tad2.isValid());
+  assert (tad2.provider() == 0);
+  assert (tad2.storeID() == StoreID::UNKNOWN);
+  assert (tad2.address() == 0);
+  assert (tad2.sgkey() == 0);
+
+  tad2.setSGKey (876);
+  assert (tad2.sgkey() == 876);
+
+  assert (tad2.transientID (123));
+  assert (!tad2.transientID (124));
+  tad2.setTransientID (124);
+  assert (tad2.transientID (124));
+  assert (tad2.transientID().size() == 2);
+
+  tad2.setAlias ("key2");
+  assert (tad2.alias().size() == 1);
+  std::set<std::string> a;
+  a.insert ("key3");
+  a.insert ("key4");
+  tad2.setAlias (a);
+  assert (tad2.alias().size() == 2);
+  assert (tad2.alias().count ("key2") == 0);
+  assert (tad2.alias().count ("key3") == 1);
+  tad2.removeAlias ("key3");
+  assert (tad2.alias().size() == 1);
+  assert (tad2.alias().count ("key3") == 0);
+
+  TestAddress ad1(1);
+  SG::TransientAddress tad3 (123, "key", &ad1);
+  assert (tad3.name() == "key");
+  assert (tad3.clID() == 123);
+  assert (tad3.isValid());
+  assert (tad3.provider() == 0);
+  assert (tad3.storeID() == StoreID::UNKNOWN);
+  assert (tad3.address() == &ad1);
+
+  TestAddress ad2(2);
+  tad3.setAddress (&ad2);
+  assert (tad3.isValid());
+  assert (tad3.address() == &ad2);
+  tad3.reset();
+  assert (!tad3.isValid());
+  assert (tad3.address() == 0);
+
+  tad3.setAddress (&ad2);
+  tad3.clearAddress (false);
+  tad3.reset();
+  assert (tad3.isValid());
+  assert (tad3.address() == &ad2);
+  tad3.clearAddress (true);
+  tad3.reset();
+  assert (!tad3.isValid());
+  assert (tad3.address() == 0);
+
+  TestProvider tp;
+  tad3.setProvider (&tp, StoreID::SPARE_STORE);
+  assert (tad3.provider() == &tp);
+  assert (tad3.storeID() == StoreID::SPARE_STORE);
+  assert (tad3.isValid());
+  tad3.consultProvider (false);
+  assert (!tad3.isValid());
+  tad3.consultProvider (true);
+  assert (tad3.isValid());
+
+  SG::TransientAddress tad4(0, "");
+  assert (tad4.clID() == CLID_NULL);
+  assert (tad4.name() == "");
+  assert (tad4.transientID().size() == 0);
+  tad4.setID (123, "key");
+  assert (tad4.name() == "key");
+  assert (tad4.clID() == 123);
+  assert (tad4.transientID().size() == 1);
+  assert (tad4.alias().size() == 0);
+}
+
+
+int main()
+{
+  test1();
+  return 0;
+}
diff --git a/Control/SGTools/test/VersionedKey_test.cxx b/Control/SGTools/test/VersionedKey_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b5fb7fd162bbb8a3390adddccba04ad2a8676e02
--- /dev/null
+++ b/Control/SGTools/test/VersionedKey_test.cxx
@@ -0,0 +1,78 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#undef NDEBUG
+
+#include "SGTools/SGVersionedKey.h"
+#include <cstring>
+#include <iostream>
+#include <stdexcept>
+#include <string>
+using namespace std;
+using namespace SG;
+
+#include <cassert>
+#define SGASSERTERROR( FALSEEXPR )   \
+    std::cerr << "Now we expect to see an error message:" << std::endl \
+              << "----Error Message Starts--->>" << std::endl; \
+    assert(!FALSEEXPR); \
+    std::cerr<< "<<---Error Message Ends-------" << std::endl
+
+int main() {
+  VersionedKey vk1("bla", 1);
+  std::string key("Bleah");
+  unsigned int version(99);
+  VersionedKey vk2(key, version);
+  VersionedKey vk3(";00;default");
+  VersionedKey vk4("default");
+
+  cout << "Versioned Key 1=" << vk1 << endl;
+  char* k1(0);
+  unsigned char v1(0);
+  vk1.decode(k1,v1);
+  assert(0 == strcmp("bla",k1));
+  assert(1 == v1);
+  cout << "Versioned Key 2=" << vk2 << endl;
+  vk2.decode(k1,v1);
+  assert(0 == strcmp("Bleah",k1));
+  assert(99 == v1);
+  assert(99 == vk2.version());
+  cout << "Versioned Key 3=" << vk3 << endl;
+  vk3.decode(k1,v1);
+  assert(0 == strcmp("default",k1));
+  assert(0 == v1);
+  vk4.decode(k1,v1);
+  assert(0 == strcmp("default",k1));
+  assert(0 == v1);
+  
+  assert(0 == strcmp("bla",    vk1.key()));
+  assert(0 == strcmp("Bleah",  vk2.key()));
+  assert(0 == strcmp("default",vk3.key()));
+
+
+  //compare vkeys
+  VersionedKey ck1("bla", 1);
+  VersionedKey ck2("bla", 2);
+  VersionedKey ck3("blu", 0);
+  VersionedKey ck4("blu", 0);
+  assert(ck1 < ck2);
+  assert(!(ck2 < ck1));
+  assert(ck1 < ck3);
+  assert(!(ck3 < ck1));
+  assert(ck2 < ck3);
+  assert(!(ck3 < ck1));
+  assert(!(ck3 < ck4));
+  assert(!(ck4 < ck3));
+
+  assert(!ck1.sameKey(ck4));
+  assert(ck3.sameKey(ck4));
+  assert(ck3.sameKey("blu"));
+  std::string bluString("blu");
+  assert(ck3.sameKey(bluString));
+
+  return 0;
+}
+
+
+
diff --git a/Control/SGTools/test/crc64_test.cxx b/Control/SGTools/test/crc64_test.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..b97ad615c93f8498b5152656b67da4b2869d9727
--- /dev/null
+++ b/Control/SGTools/test/crc64_test.cxx
@@ -0,0 +1,48 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id: crc64_test.cxx,v 1.2 2007-03-08 02:02:06 ssnyder Exp $
+/**
+ * @file  SGTools/crc64_test.cxx
+ * @author scott snyder, originally from David T. Jones
+ * @date Mar 2007
+ * @brief Regression tests for CRC-64 calculation.
+ */
+
+#undef NDEBUG
+
+#include "SGTools/crc64.h"
+#include <iostream>
+#include <cassert>
+
+
+void testextend (const std::string& str, unsigned int x)
+{
+  uint64_t crc1 = SG::crc64 (str);
+  crc1 = SG::crc64addint (crc1, x);
+
+  std::string str2 = str;
+  while (x > 0) {
+    str2.push_back ((char)(x&0xff));
+    x >>= 8;
+  }
+  assert (crc1 == SG::crc64 (str2));
+}
+
+
+int main()
+{
+  const char* testin1 = "MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGTVIRGATTSYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE";
+  const char* testout1 = "C874767DA8254746";
+  const char* testin2 = "MNIIQGNLVGTGLKIGIVVGRFNDFITSKLLSGAEDALLRHGVDTNDIDVAWVPGAFEIPFAAKKMAETKKYDAIITLGDVIRGATTHYDYVCNEAAKGIAQAANTTGVPVIFGIVTTENIEQAIERAGTKAGNKGVDCAVSAIEMANLNRSFE"; /* Differs from 1st seq in two places */
+  const char* testout2 = "2DF1AA17420FCA3F";
+
+  assert (SG::crc64digest (testin1) == std::string (testout1));
+  assert (SG::crc64digest (testin2) == std::string (testout2));
+
+  testextend (testin1, 54356);
+  testextend (testin2, 9812674);
+  return 0;
+}
+
diff --git a/Control/SGTools/test/exceptions_test.cxx b/Control/SGTools/test/exceptions_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..aacbba6b705f67c26ae23d740d47a8c50a929d85
--- /dev/null
+++ b/Control/SGTools/test/exceptions_test.cxx
@@ -0,0 +1,32 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// $Id$
+/**
+ * @file SGTools/test/exceptions_test.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Feb, 2014
+ * @brief Regression tests for exceptions.
+ */
+
+#undef NDEBUG
+#include "SGTools/exceptions.h"
+#include <iostream>
+
+
+void test1()
+{
+  std::cout << "test1\n";
+
+  std::cout << SG::ExcBadDataProxyCast (123, typeid(int)).what() << "\n";
+
+  std::cout << SG::ExcProxyCollision (123, "abc", 456, "def").what() << "\n";
+}
+
+
+int main()
+{
+  test1();
+  return 0;
+}
diff --git a/Control/SGTools/test/safe_clid_test.cxx b/Control/SGTools/test/safe_clid_test.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..c5a042c6e9c642e8a169dd831852150bfb0833f0
--- /dev/null
+++ b/Control/SGTools/test/safe_clid_test.cxx
@@ -0,0 +1,31 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#undef NDEBUG
+
+#include "SGTools/safe_clid.h"
+#include "SGTools/CLASS_DEF.h"
+#include "GaudiKernel/DataObject.h"
+#include <cassert>
+
+#include <iostream>
+
+struct A {};
+struct B {};
+CLASS_DEF (B, 98765, 0)
+struct C
+  : public DataObject
+{
+  static CLID& classID() { static CLID clid =  44444; return clid; }
+};
+
+int main()
+{
+  assert (SG::safe_clid<int> () == 0);
+  assert (SG::safe_clid<A> () == 0);
+  assert (SG::safe_clid<B> () == 98765);
+  assert (SG::safe_clid<C> () == 44444);
+  return 0;
+}
+