text:
#ifndef BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED
#define BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED

//  local_shared_ptr.hpp
//
//  Copyright 2017 Peter Dimov
//
//  Distributed under the Boost Software License, Version 1.0. (See
//  accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//
//  See http://www.boost.org/libs/smart_ptr/ for documentation.

#include <boost/smart_ptr/shared_ptr.hpp>

namespace boost {

template <class T> class local_shared_ptr;

namespace detail {

template <class E, class Y>
inline void lsp_pointer_construct(boost::local_shared_ptr<E> * /*ppx*/, Y *p,
                                  boost::detail::local_counted_base *&pn) {
  boost::detail::sp_assert_convertible<Y, E>();

  typedef boost::detail::local_sp_deleter<boost::checked_deleter<Y>> D;

  boost::shared_ptr<E> p2(p, D());

  D *pd = static_cast<D *>(p2._internal_get_untyped_deleter());

  pd->pn_ = p2._internal_count();

  pn = pd;
}

template <class E, class Y>
inline void lsp_pointer_construct(boost::local_shared_ptr<E[]> * /*ppx*/, Y *p,
                                  boost::detail::local_counted_base *&pn) {
  boost::detail::sp_assert_convertible<Y[], E[]>();

  typedef boost::detail::local_sp_deleter<boost::checked_array_deleter<E>> D;

  boost::shared_ptr<E[]> p2(p, D());

  D *pd = static_cast<D *>(p2._internal_get_untyped_deleter());

  pd->pn_ = p2._internal_count();

  pn = pd;
}

template <class E, std::size_t N, class Y>
inline void lsp_pointer_construct(boost::local_shared_ptr<E[N]> * /*ppx*/, Y *p,
                                  boost::detail::local_counted_base *&pn) {
  boost::detail::sp_assert_convertible<Y[N], E[N]>();

  typedef boost::detail::local_sp_deleter<boost::checked_array_deleter<E>> D;

  boost::shared_ptr<E[N]> p2(p, D());

  D *pd = static_cast<D *>(p2._internal_get_untyped_deleter());

  pd->pn_ = p2._internal_count();

  pn = pd;
}

template <class E, class P, class D>
inline void lsp_deleter_construct(boost::local_shared_ptr<E> * /*ppx*/, P p,
                                  D const &d,
                                  boost::detail::local_counted_base *&pn) {
  typedef boost::detail::local_sp_deleter<D> D2;

  boost::shared_ptr<E> p2(p, D2(d));

  D2 *pd = static_cast<D2 *>(p2._internal_get_untyped_deleter());

  pd->pn_ = p2._internal_count();

  pn = pd;
}

template <class E, class P, class D, class A>
inline void lsp_allocator_construct(boost::local_shared_ptr<E> * /*ppx*/, P p,
                                    D const &d, A const &a,
                                    boost::detail::local_counted_base *&pn) {
  typedef boost::detail::local_sp_deleter<D> D2;

  boost::shared_ptr<E> p2(p, D2(d), a);

  D2 *pd = static_cast<D2 *>(p2._internal_get_untyped_deleter());

  pd->pn_ = p2._internal_count();

  pn = pd;
}

struct lsp_internal_constructor_tag {};

} // namespace detail

//
// local_shared_ptr
//
// as shared_ptr, but local to a thread.
// reference count manipulations are non-atomic.
//

template <class T> class local_shared_ptr {
private:
  typedef local_shared_ptr this_type;

public:
  typedef typename boost::detail::sp_element<T>::type element_type;

private:
  element_type *px;
  boost::detail::local_counted_base *pn;

  template <class Y> friend class local_shared_ptr;

public:
  // destructor

  ~local_shared_ptr() BOOST_SP_NOEXCEPT {
    if (pn) {
      pn->release();
    }
  }

  // constructors

  BOOST_CONSTEXPR local_shared_ptr() BOOST_SP_NOEXCEPT : px(0), pn(0) {}

#if !defined(BOOST_NO_CXX11_NULLPTR)

  BOOST_CONSTEXPR
  local_shared_ptr(boost::detail::sp_nullptr_t) BOOST_SP_NOEXCEPT : px(0),
                                                                    pn(0) {}

#endif

  // internal constructor, used by make_shared
  BOOST_CONSTEXPR
  local_shared_ptr(boost::detail::lsp_internal_constructor_tag,
                   element_type *px_,
                   boost::detail::local_counted_base *pn_) BOOST_SP_NOEXCEPT
      : px(px_),
        pn(pn_) {}

  template <class Y> explicit local_shared_ptr(Y *p) : px(p), pn(0) {
    boost::detail::lsp_pointer_construct(this, p, pn);
  }

  template <class Y, class D> local_shared_ptr(Y *p, D d) : px(p), pn(0) {
    boost::detail::lsp_deleter_construct(this, p, d, pn);
  }

#if !defined(BOOST_NO_CXX11_NULLPTR)

  template <class D>
  local_shared_ptr(boost::detail::sp_nullptr_t p, D d) : px(p), pn(0) {
    boost::detail::lsp_deleter_construct(this, p, d, pn);
  }

#endif

  template <class Y, class D, class A>
  local_shared_ptr(Y *p, D d, A a) : px(p), pn(0) {
    boost::detail::lsp_allocator_construct(this, p, d, a, pn);
  }

#if !defined(BOOST_NO_CXX11_NULLPTR)

  template <class D, class A>
  local_shared_ptr(boost::detail::sp_nullptr_t p, D d, A a) : px(p), pn(0) {
    boost::detail::lsp_allocator_construct(this, p, d, a, pn);
  }

#endif

  // construction from shared_ptr

  template <class Y>
  local_shared_ptr(
      shared_ptr<Y> const &r,
      typename boost::detail::sp_enable_if_convertible<Y, T>::type =
          boost::detail::sp_empty())
      : px(r.get()), pn(0) {
    boost::detail::sp_assert_convertible<Y, T>();

    if (r.use_count() != 0) {
      pn = new boost::detail::local_counted_impl(r._internal_count());
    }
  }

#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)

  template <class Y>
  local_shared_ptr(
      shared_ptr<Y> &&r,
      typename boost::detail::sp_enable_if_convertible<Y, T>::type =
          boost::detail::sp_empty())
      : px(r.get()), pn(0) {
    boost::detail::sp_assert_convertible<Y, T>();

    if (r.use_count() != 0) {
      pn = new boost::detail::local_counted_impl(r._internal_count());
      r.reset();
    }
  }

#endif

  // construction from unique_ptr

#if !defined(BOOST_NO_CXX11_SMART_PTR) &&                                      \
    !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)

  template <class Y, class D>
  local_shared_ptr(
      std::unique_ptr<Y, D> &&r,
      typename boost::detail::sp_enable_if_convertible<Y, T>::type =
          boost::detail::sp_empty())
      : px(r.get()), pn(0) {
    boost::detail::sp_assert_convertible<Y, T>();

    if (px) {
      pn = new boost::detail::local_counted_impl(
          shared_ptr<T>(std::move(r))._internal_count());
    }
  }

#endif

  template <class Y, class D>
  local_shared_ptr(boost::movelib::unique_ptr<Y, D> r); // !
  //  : px( r.get() ), pn( new boost::detail::local_counted_impl( shared_ptr<T>(
  //  std::move(r) ) ) )
  //{
  //    boost::detail::sp_assert_convertible< Y, T >();
  //}

  // copy constructor

  local_shared_ptr(local_shared_ptr const &r) BOOST_SP_NOEXCEPT : px(r.px),
                                                                  pn(r.pn) {
    if (pn) {
      pn->add_ref();
    }
  }

  // move constructor

#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)

  local_shared_ptr(local_shared_ptr &&r) BOOST_SP_NOEXCEPT : px(r.px),
                                                             pn(r.pn) {
    r.px = 0;
    r.pn = 0;
  }

#endif

  // converting copy constructor

  template <class Y>
  local_shared_ptr(
      local_shared_ptr<Y> const &r,
      typename boost::detail::sp_enable_if_convertible<Y, T>::type =
          boost::detail::sp_empty()) BOOST_SP_NOEXCEPT : px(r.px),
                                                         pn(r.pn) {
    boost::detail::sp_assert_convertible<Y, T>();

    if (pn) {
      pn->add_ref();
    }
  }

  // converting move constructor

#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)

  template <class Y>
  local_shared_ptr(
      local_shared_ptr<Y> &&r,
      typename boost::detail::sp_enable_if_convertible<Y, T>::type =
          boost::detail::sp_empty()) BOOST_SP_NOEXCEPT : px(r.px),
                                                         pn(r.pn) {
    boost::detail::sp_assert_convertible<Y, T>();

    r.px = 0;
    r.pn = 0;
  }

#endif

  // aliasing

  template <class Y>
  local_shared_ptr(local_shared_ptr<Y> const &r,
                   element_type *p) BOOST_SP_NOEXCEPT : px(p),
                                                        pn(r.pn) {
    if (pn) {
      pn->add_ref();
    }
  }

#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)

  template <class Y>
  local_shared_ptr(local_shared_ptr<Y> &&r, element_type *p) BOOST_SP_NOEXCEPT
      : px(p),
        pn(r.pn) {
    r.px = 0;
    r.pn = 0;
  }

#endif

  // assignment

  local_shared_ptr &operator=(local_shared_ptr const &r) BOOST_SP_NOEXCEPT {
    local_shared_ptr(r).swap(*this);
    return *this;
  }

  template <class Y>
  local_shared_ptr &operator=(local_shared_ptr<Y> const &r) BOOST_SP_NOEXCEPT {
    local_shared_ptr(r).swap(*this);
    return *this;
  }

#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)

  local_shared_ptr &operator=(local_shared_ptr &&r) BOOST_SP_NOEXCEPT {
    local_shared_ptr(std::move(r)).swap(*this);
    return *this;
  }

  template <class Y>
  local_shared_ptr &operator=(local_shared_ptr<Y> &&r) BOOST_SP_NOEXCEPT {
    local_shared_ptr(std::move(r)).swap(*this);
    return *this;
  }

#endif

#if !defined(BOOST_NO_CXX11_NULLPTR)

  local_shared_ptr &operator=(boost::detail::sp_nullptr_t) BOOST_SP_NOEXCEPT {
    local_shared_ptr().swap(*this);
    return *this;
  }

#endif

#if !defined(BOOST_NO_CXX11_SMART_PTR) &&                                      \
    !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)

  template <class Y, class D>
  local_shared_ptr &operator=(std::unique_ptr<Y, D> &&r) {
    local_shared_ptr(std::move(r)).swap(*this);
    return *this;
  }

#endif

  template <class Y, class D>
  local_shared_ptr &operator=(boost::movelib::unique_ptr<Y, D> r); // !

  // reset

  void reset() BOOST_SP_NOEXCEPT { local_shared_ptr().swap(*this); }

  template <class Y>
  void reset(Y *p) // Y must be complete
  {
    local_shared_ptr(p).swap(*this);
  }

  template <class Y, class D> void reset(Y *p, D d) {
    local_shared_ptr(p, d).swap(*this);
  }

  template <class Y, class D, class A> void reset(Y *p, D d, A a) {
    local_shared_ptr(p, d, a).swap(*this);
  }

  template <class Y>
  void reset(local_shared_ptr<Y> const &r, element_type *p) BOOST_SP_NOEXCEPT {
    local_shared_ptr(r, p).swap(*this);
  }

#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)

  template <class Y>
  void reset(local_shared_ptr<Y> &&r, element_type *p) BOOST_SP_NOEXCEPT {
    local_shared_ptr(std::move(r), p).swap(*this);
  }

#endif

  // accessors

  typename boost::detail::sp_dereference<T>::type
  operator*() const BOOST_SP_NOEXCEPT {
    return *px;
  }

  typename boost::detail::sp_member_access<T>::type
  operator->() const BOOST_SP_NOEXCEPT {
    return px;
  }

  typename boost::detail::sp_array_access<T>::type
  operator[](std::ptrdiff_t i) const BOOST_SP_NOEXCEPT_WITH_ASSERT {
    BOOST_ASSERT(px != 0);
    BOOST_ASSERT(i >= 0 && (i < boost::detail::sp_extent<T>::value ||
                            boost::detail::sp_extent<T>::value == 0));

    return static_cast<typename boost::detail::sp_array_access<T>::type>(px[i]);
  }

  element_type *get() const BOOST_SP_NOEXCEPT { return px; }

  // implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>

  long local_use_count() const BOOST_SP_NOEXCEPT {
    return pn ? pn->local_use_count() : 0;
  }

  // conversions to shared_ptr, weak_ptr

#if !defined(BOOST_SP_NO_SP_CONVERTIBLE) &&                                    \
    !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
  template <class Y, class E = typename boost::detail::sp_enable_if_convertible<
                         T, Y>::type>
  operator shared_ptr<Y>() const BOOST_SP_NOEXCEPT
#else
  template <class Y>
  operator shared_ptr<Y>() const BOOST_SP_NOEXCEPT
#endif
  {
    boost::detail::sp_assert_convertible<T, Y>();

    if (pn) {
      return shared_ptr<Y>(boost::detail::sp_internal_constructor_tag(), px,
                           pn->local_cb_get_shared_count());
    } else {
      return shared_ptr<Y>();
    }
  }

#if !defined(BOOST_SP_NO_SP_CONVERTIBLE) &&                                    \
    !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS)
  template <class Y, class E = typename boost::detail::sp_enable_if_convertible<
                         T, Y>::type>
  operator weak_ptr<Y>() const BOOST_SP_NOEXCEPT
#else
  template <class Y>
  operator weak_ptr<Y>() const BOOST_SP_NOEXCEPT
#endif
  {
    boost::detail::sp_assert_convertible<T, Y>();

    if (pn) {
      return shared_ptr<Y>(boost::detail::sp_internal_constructor_tag(), px,
                           pn->local_cb_get_shared_count());
    } else {
      return weak_ptr<Y>();
    }
  }

  // swap

  void swap(local_shared_ptr &r) BOOST_SP_NOEXCEPT {
    std::swap(px, r.px);
    std::swap(pn, r.pn);
  }

  // owner_before

  template <class Y>
  bool owner_before(local_shared_ptr<Y> const &r) const BOOST_SP_NOEXCEPT {
    return std::less<boost::detail::local_counted_base *>()(pn, r.pn);
  }
};

template <class T, class U>
inline bool operator==(local_shared_ptr<T> const &a,
                       local_shared_ptr<U> const &b) BOOST_SP_NOEXCEPT {
  return a.get() == b.get();
}

template <class T, class U>
inline bool operator!=(local_shared_ptr<T> const &a,
                       local_shared_ptr<U> const &b) BOOST_SP_NOEXCEPT {
  return a.get() != b.get();
}

#if !defined(BOOST_NO_CXX11_NULLPTR)

template <class T>
inline bool operator==(local_shared_ptr<T> const &p,
                       boost::detail::sp_nullptr_t) BOOST_SP_NOEXCEPT {
  return p.get() == 0;
}

template <class T>
inline bool operator==(boost::detail::sp_nullptr_t,
                       local_shared_ptr<T> const &p) BOOST_SP_NOEXCEPT {
  return p.get() == 0;
}

template <class T>
inline bool operator!=(local_shared_ptr<T> const &p,
                       boost::detail::sp_nullptr_t) BOOST_SP_NOEXCEPT {
  return p.get() != 0;
}

template <class T>
inline bool operator!=(boost::detail::sp_nullptr_t,
                       local_shared_ptr<T> const &p) BOOST_SP_NOEXCEPT {
  return p.get() != 0;
}

#endif

template <class T, class U>
inline bool operator==(local_shared_ptr<T> const &a,
                       shared_ptr<U> const &b) BOOST_SP_NOEXCEPT {
  return a.get() == b.get();
}

template <class T, class U>
inline bool operator!=(local_shared_ptr<T> const &a,
                       shared_ptr<U> const &b) BOOST_SP_NOEXCEPT {
  return a.get() != b.get();
}

template <class T, class U>
inline bool operator==(shared_ptr<T> const &a,
                       local_shared_ptr<U> const &b) BOOST_SP_NOEXCEPT {
  return a.get() == b.get();
}

template <class T, class U>
inline bool operator!=(shared_ptr<T> const &a,
                       local_shared_ptr<U> const &b) BOOST_SP_NOEXCEPT {
  return a.get() != b.get();
}

template <class T, class U>
inline bool operator<(local_shared_ptr<T> const &a,
                      local_shared_ptr<U> const &b) BOOST_SP_NOEXCEPT {
  return a.owner_before(b);
}

template <class T>
inline void swap(local_shared_ptr<T> &a,
                 local_shared_ptr<T> &b) BOOST_SP_NOEXCEPT {
  a.swap(b);
}

template <class T, class U>
local_shared_ptr<T>
static_pointer_cast(local_shared_ptr<U> const &r) BOOST_SP_NOEXCEPT {
  (void)static_cast<T *>(static_cast<U *>(0));

  typedef typename local_shared_ptr<T>::element_type E;

  E *p = static_cast<E *>(r.get());
  return local_shared_ptr<T>(r, p);
}

template <class T, class U>
local_shared_ptr<T>
const_pointer_cast(local_shared_ptr<U> const &r) BOOST_SP_NOEXCEPT {
  (void)const_cast<T *>(static_cast<U *>(0));

  typedef typename local_shared_ptr<T>::element_type E;

  E *p = const_cast<E *>(r.get());
  return local_shared_ptr<T>(r, p);
}

template <class T, class U>
local_shared_ptr<T>
dynamic_pointer_cast(local_shared_ptr<U> const &r) BOOST_SP_NOEXCEPT {
  (void)dynamic_cast<T *>(static_cast<U *>(0));

  typedef typename local_shared_ptr<T>::element_type E;

  E *p = dynamic_cast<E *>(r.get());
  return p ? local_shared_ptr<T>(r, p) : local_shared_ptr<T>();
}

template <class T, class U>
local_shared_ptr<T>
reinterpret_pointer_cast(local_shared_ptr<U> const &r) BOOST_SP_NOEXCEPT {
  (void)reinterpret_cast<T *>(static_cast<U *>(0));

  typedef typename local_shared_ptr<T>::element_type E;

  E *p = reinterpret_cast<E *>(r.get());
  return local_shared_ptr<T>(r, p);
}

#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)

template <class T, class U>
local_shared_ptr<T>
static_pointer_cast(local_shared_ptr<U> &&r) BOOST_SP_NOEXCEPT {
  (void)static_cast<T *>(static_cast<U *>(0));

  typedef typename local_shared_ptr<T>::element_type E;

  E *p = static_cast<E *>(r.get());
  return local_shared_ptr<T>(std::move(r), p);
}

template <class T, class U>
local_shared_ptr<T>
const_pointer_cast(local_shared_ptr<U> &&r) BOOST_SP_NOEXCEPT {
  (void)const_cast<T *>(static_cast<U *>(0));

  typedef typename local_shared_ptr<T>::element_type E;

  E *p = const_cast<E *>(r.get());
  return local_shared_ptr<T>(std::move(r), p);
}

template <class T, class U>
local_shared_ptr<T>
dynamic_pointer_cast(local_shared_ptr<U> &&r) BOOST_SP_NOEXCEPT {
  (void)dynamic_cast<T *>(static_cast<U *>(0));

  typedef typename local_shared_ptr<T>::element_type E;

  E *p = dynamic_cast<E *>(r.get());
  return p ? local_shared_ptr<T>(std::move(r), p) : local_shared_ptr<T>();
}

template <class T, class U>
local_shared_ptr<T>
reinterpret_pointer_cast(local_shared_ptr<U> &&r) BOOST_SP_NOEXCEPT {
  (void)reinterpret_cast<T *>(static_cast<U *>(0));

  typedef typename local_shared_ptr<T>::element_type E;

  E *p = reinterpret_cast<E *>(r.get());
  return local_shared_ptr<T>(std::move(r), p);
}

#endif // !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )

// get_pointer() enables boost::mem_fn to recognize local_shared_ptr

template <class T>
inline typename local_shared_ptr<T>::element_type *
get_pointer(local_shared_ptr<T> const &p) BOOST_SP_NOEXCEPT {
  return p.get();
}

// operator<<

#if !defined(BOOST_NO_IOSTREAM)

template <class E, class T, class Y>
std::basic_ostream<E, T> &operator<<(std::basic_ostream<E, T> &os,
                                     local_shared_ptr<Y> const &p) {
  os << p.get();
  return os;
}

#endif // !defined(BOOST_NO_IOSTREAM)

// get_deleter

template <class D, class T>
D *get_deleter(local_shared_ptr<T> const &p) BOOST_SP_NOEXCEPT {
  return get_deleter<D>(shared_ptr<T>(p));
}

// hash_value

template <class T> struct hash;

template <class T>
std::size_t hash_value(local_shared_ptr<T> const &p) BOOST_SP_NOEXCEPT {
  return boost::hash<typename local_shared_ptr<T>::element_type *>()(p.get());
}

} // namespace boost

#endif // #ifndef BOOST_SMART_PTR_LOCAL_SHARED_PTR_HPP_INCLUDED


text:
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
// ------------------------------------------------------------

#include "stdafx.h"

#include <stdlib.h>
#include <boost/test/unit_test.hpp>
#include "Common/boost-taef.h"

namespace Data
{
    namespace Integration
    {
        using namespace Common;
        using namespace ktl;
        using namespace Data::Utilities;
        using namespace TxnReplicator;
        using namespace TxnReplicator::TestCommon;

        StringLiteral const TraceComponent("BackupTests");
        std::wstring const TestLogFileName(L"ComTransactionalReplicatorTest.log");

        class BackupTests
        {
        public:
            Awaitable<void> Run_Backup_Concurency_Backup_ChangeRoleOrClose_DrainTheBackup(
                __in wstring const & workFolder,
                __in wstring const & backupFolder,
                __in wstring const & testFolderPath,
                __in int numberOfStateProviders,
                __in int numberOfTxnPerSP,
                __in int numberOfOperationPerTxn,
                __in bool immediatelyClose,
                __in FABRIC_REPLICA_ROLE replicaRole);

        public:
            Awaitable<void> Test_RestoreIncremental(
                __in wstring const & workFolder,
                __in wstring const & backupFolder,
                __in int numberOfStateProvidersInFullCheckpoint,
                __in int numberOfStateProvidersPerIteration,
                __in int numberOfIterations,
                __in Data::Log::LogManager & logManager,
                __in KGuid const & sourcePartitionId,
                __in FABRIC_REPLICA_ID sourceReplicaID,
                __in KGuid const & targetPartitionId,
                __in FABRIC_REPLICA_ID targetReplicaID,
                __in FABRIC_RESTORE_POLICY policy);

            Awaitable<void> Test_Backup_Concurency_Backup_ChangeRoleOrClose_DrainTheBackup(
                __in wstring const & workFolder,
                __in wstring const & backupFolder,
                __in Data::Log::LogManager & logManager,
                __in KGuid const & sourcePartitionId,
                __in FABRIC_REPLICA_ID sourceReplicaID,
                __in int numberOfStateProviders,
                __in int numberOfTxnPerSP,
                __in int numberOfOperationPerTxn,
                __in bool immediatelyClose,
                __in FABRIC_REPLICA_ROLE replicaRole);

        protected:
            static bool IsSameReplica(
                __in KGuid const & sourcePartitionId,
                __in FABRIC_REPLICA_ID sourceReplicaID,
                __in KGuid const & targetPartitionId,
                __in FABRIC_REPLICA_ID targetReplicaID);

            template<class TKey, class TValue>
            static NTSTATUS GetStore(
                __in ITransactionalReplicator & replicator,
                __in KUri const & stateProviderName,
                __out typename Data::TStore::IStore<TKey, TValue>::SPtr & store);

            static Awaitable<NTSTATUS> PopulateAsync(
                __in KtlSystem & system,
                __in ITransactionalReplicator & replicator,
                __in Data::TStore::IStore<int, int> & store,
                __in int startingKey,
                __in int numberOfTxns,
                __in int numberOfOperationsPerTxn) noexcept;

        protected:
            wstring CreateFileName(
                __in wstring const & folderName);

            void InitializeKtlConfig(
                __in std::wstring workDir,
                __in std::wstring fileName,
                __in KAllocator & allocator,
                __out KtlLogger::SharedLogSettingsSPtr & sharedLogSettings);

            KUri::CSPtr GetStateProviderName(
                __in int stateProviderIndex);

            void EndTest();

        private:
            void VerifyStateProviderExists(
                __in ITransactionalReplicator & replicator,
                __in KUri const & stateProviderName);

        protected:
            CommonConfig config; // load the configuration object as its needed for the tracing to work
            KtlSystem * underlyingSystem_;
        };

        Awaitable<void> BackupTests::Run_Backup_Concurency_Backup_ChangeRoleOrClose_DrainTheBackup(
            __in wstring const & workFolder,
            __in wstring const & backupFolder,
            __in wstring const & testFolderPath,
            __in int numberOfStateProviders,
            __in int numberOfTxnPerSP,
            __in int numberOfOperationPerTxn,
            __in bool immediatelyClose,
            __in FABRIC_REPLICA_ROLE replicaRole)
        {
            NTSTATUS status = STATUS_UNSUCCESSFUL;

            // KTL test input
            KGuid sourcePartitionId;
            sourcePartitionId.CreateNew();
            FABRIC_REPLICA_ID sourceReplicaId = 777;

            KtlLogger::SharedLogSettingsSPtr sharedLogSettings;
            InitializeKtlConfig(testFolderPath, TestLogFileName, underlyingSystem_->NonPagedAllocator(), sharedLogSettings);

            Data::Log::LogManager::SPtr logManager;
            status = Data::Log::LogManager::Create(underlyingSystem_->NonPagedAllocator(), logManager);
            CODING_ERROR_ASSERT(NT_SUCCESS(status));

            status = co_await logManager->OpenAsync(CancellationToken::None, sharedLogSettings);
            CODING_ERROR_ASSERT(NT_SUCCESS(status));

            co_await Test_Backup_Concurency_Backup_ChangeRoleOrClose_DrainTheBackup(
                workFolder,
                backupFolder,
                *logManager,
                sourcePartitionId,
                sourceReplicaId,
                numberOfStateProviders,
                numberOfTxnPerSP,
                numberOfOperationPerTxn,
                immediatelyClose,
                replicaRole);

            status = co_await logManager->CloseAsync(CancellationToken::None);
            CODING_ERROR_ASSERT(NT_SUCCESS(status));
            logManager = nullptr;

            co_return;
        }

        Awaitable<void> BackupTests::Test_RestoreIncremental(
            __in wstring const & testFolder,
            __in wstring const & backupFolder,
            __in int numberOfStateProvidersInFullCheckpoint,
            __in int numberOfStateProvidersPerIteration,
            __in int numberOfIterations,
            __in Data::Log::LogManager & logManager,
            __in KGuid const & sourcePartitionId,
            __in FABRIC_REPLICA_ID sourceReplicaID,
            __in KGuid const & targetPartitionId,
            __in FABRIC_REPLICA_ID targetReplicaID,
            __in FABRIC_RESTORE_POLICY policy)
        {
            NTSTATUS status = STATUS_UNSUCCESSFUL;

            KAllocator & allocator = underlyingSystem_->PagedAllocator();

            // #10145496: Using TStore instead of TSP here.
            TxnReplicator::TestCommon::TestStateProviderFactory::SPtr stateProviderFactory = TxnReplicator::TestCommon::TestStateProviderFactory::Create(
                allocator);

            KString::SPtr backupFolderPath = KPath::CreatePath(backupFolder.c_str(), allocator);
            TestBackupCallbackHandler::SPtr backupCallbackHandler = TestBackupCallbackHandler::Create(
                *backupFolderPath,
                allocator);

            Data::Utilities::OperationData::SPtr initParams = Data::Utilities::OperationData::Create(allocator);
            Data::Utilities::BinaryWriter bw(allocator);
            bw.Write(L"Initial Value", Data::Utilities::UTF16);
            initParams->Append(*bw.GetBuffer(0));

            int lastInsertedStateProviderIndex = -1;
            {
                Replica::SPtr replica = Replica::Create(
                    sourcePartitionId,
                    sourceReplicaID,
                    testFolder,
                    logManager,
                    allocator,
                    stateProviderFactory.RawPtr());

                co_await replica->OpenAsync();

                // Become Primary after open:
                // 1. Update Status: Pending
                // 2. New Epoch with new data loss number.
                // 3. Change Role to Primary
                // 4. Update Status: Granted.
                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_RECONFIGURATION_PENDING);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_RECONFIGURATION_PENDING);

                FABRIC_EPOCH epoch1; epoch1.DataLossNumber = 1; epoch1.ConfigurationNumber = 1; epoch1.Reserved = nullptr;
                co_await replica->ChangeRoleAsync(epoch1, FABRIC_REPLICA_ROLE_PRIMARY);

                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_GRANTED);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_GRANTED);

                KStringView typeName(
                    (PWCHAR)TestStateProvider::TypeName.cbegin(),
                    (ULONG)TestStateProvider::TypeName.size() + 1,
                    (ULONG)TestStateProvider::TypeName.size());
                for (int i = 0; i < numberOfStateProvidersInFullCheckpoint; ++i)
                {
                    Transaction::SPtr txn;
                    replica->TxnReplicator->CreateTransaction(txn);
                    KFinally([&] {txn->Dispose(); });

                    KUri::CSPtr stateProviderName = GetStateProviderName(++lastInsertedStateProviderIndex);
                    status = co_await replica->TxnReplicator->AddAsync(
                        *txn,
                        *stateProviderName,
                        typeName,
                        initParams.RawPtr());
                    VERIFY_IS_TRUE(NT_SUCCESS(status));
                    co_await txn->CommitAsync();
                }

                status = replica->TxnReplicator->Test_RequestCheckpointAfterNextTransaction();
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                for (int iteration = 0; iteration < numberOfIterations; ++iteration)
                {
                    for (int i = 0; i < numberOfStateProvidersPerIteration; ++i)
                    {
                        Transaction::SPtr txn;
                        replica->TxnReplicator->CreateTransaction(txn);
                        KFinally([&] {txn->Dispose(); });

                        KUri::CSPtr stateProviderName = GetStateProviderName(++lastInsertedStateProviderIndex);
                        status = co_await replica->TxnReplicator->AddAsync(
                            *txn,
                            *stateProviderName,
                            typeName,
                            initParams.RawPtr());
                        VERIFY_IS_TRUE(NT_SUCCESS(status));
                        co_await txn->CommitAsync();
                    }

                    if (iteration == 0)
                    {
                        BackupInfo result;
                        status = co_await replica->TxnReplicator->BackupAsync(*backupCallbackHandler, result);
                        VERIFY_IS_TRUE(NT_SUCCESS(status));
                    }
                    else
                    {
                        BackupInfo result;
                        status = co_await replica->TxnReplicator->BackupAsync(*backupCallbackHandler, FABRIC_BACKUP_OPTION_INCREMENTAL, Common::TimeSpan::FromMinutes(4), CancellationToken::None, result);
                        VERIFY_IS_TRUE(NT_SUCCESS(status));
                    }
                }

                // Close the replica:
                // 1. Update Status: NOT PRIMARY
                // 2. Close
                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_NOT_PRIMARY);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_NOT_PRIMARY);

                bool isSameReplica = IsSameReplica(sourcePartitionId, sourceReplicaID, targetPartitionId, targetReplicaID);
                if (isSameReplica == false)
                {
                    FABRIC_EPOCH epoch3; epoch3.DataLossNumber = 1; epoch3.ConfigurationNumber = 2; epoch3.Reserved = nullptr;
                    co_await replica->ChangeRoleAsync(epoch3, FABRIC_REPLICA_ROLE_NONE);
                }

                co_await replica->CloseAsync();
            }

            {
                TestDataLossHandler::SPtr dataLossHandler = TestDataLossHandler::Create(
                    allocator,
                    backupFolderPath.RawPtr(),
                    policy);

                Replica::SPtr replica = Replica::Create(
                    targetPartitionId,
                    targetReplicaID,
                    testFolder,
                    logManager,
                    allocator,
                    stateProviderFactory.RawPtr(),
                    nullptr,
                    dataLossHandler.RawPtr());

                dataLossHandler->Initialize(*replica->TxnReplicator);

                // Open the replica.
                co_await replica->OpenAsync();

                // Become Primary after open (For OnDataLossAsync):
                // 1. Update Status: Pending
                // 2. New Epoch with new data loss number.
                // 3. Change Role to Primary
                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_RECONFIGURATION_PENDING);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_RECONFIGURATION_PENDING);

                FABRIC_EPOCH epoch2; epoch2.DataLossNumber = 2; epoch2.ConfigurationNumber = 2; epoch2.Reserved = nullptr;
                co_await replica->ChangeRoleAsync(epoch2, FABRIC_REPLICA_ROLE_PRIMARY);

                // Get OnDataLossAsync and become fully Primary
                // 1. OnDataLossAsync
                // 2. Update Status: Granted
                // TODO: UpdateCatchupConfig & WaitForQuorumCatchup for 1 replica?
                BOOLEAN isStateChanged = false;
                status = co_await replica->OnDataLossAsync(isStateChanged);
                VERIFY_IS_TRUE(NT_SUCCESS(status));
                VERIFY_IS_TRUE(isStateChanged == TRUE);

                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_GRANTED);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_GRANTED);

                // Verify that the replica is latest version number after recovery.
                {
                    FABRIC_EPOCH currentEpoch;
                    status = replica->TxnReplicator->GetCurrentEpoch(currentEpoch);
                    VERIFY_IS_TRUE(NT_SUCCESS(status));

                    VERIFY_ARE_EQUAL(epoch2.DataLossNumber, 2);
                    VERIFY_ARE_EQUAL(epoch2.ConfigurationNumber, 2);
                }

                // Verify restored state
                for (int i = 0; i <= lastInsertedStateProviderIndex; i++)
                {
                    VerifyStateProviderExists(*replica->TxnReplicator, *GetStateProviderName(i));
                }

                // Drop the replica:
                // 1. Update Status: NOT PRIMARY
                // 2. Change Role to None
                // 3. Close
                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_NOT_PRIMARY);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_NOT_PRIMARY);

                FABRIC_EPOCH epoch3; epoch3.DataLossNumber = 2; epoch3.ConfigurationNumber = 3; epoch3.Reserved = nullptr;
                co_await replica->ChangeRoleAsync(epoch3, FABRIC_REPLICA_ROLE_NONE);

                co_await replica->CloseAsync();
            }

            co_return;
        }

        Awaitable<void> BackupTests::Test_Backup_Concurency_Backup_ChangeRoleOrClose_DrainTheBackup(
            __in wstring const & workFolder,
            __in wstring const & backupFolder,
            __in Data::Log::LogManager & logManager,
            __in KGuid const & sourcePartitionId,
            __in FABRIC_REPLICA_ID sourceReplicaID,
            __in int numberOfStateProviders,
            __in int numberOfTxnPerSP,
            __in int numberOfOperationPerTxn,
            __in bool immediatelyClose,
            __in FABRIC_REPLICA_ROLE replicaRole)
        {
            NTSTATUS status = STATUS_UNSUCCESSFUL;

            // Verify the inputs.
            if (immediatelyClose)
            {
                VERIFY_ARE_EQUAL(replicaRole, FABRIC_REPLICA_ROLE_UNKNOWN);
            }
            else
            {
                VERIFY_IS_TRUE(replicaRole == FABRIC_REPLICA_ROLE_ACTIVE_SECONDARY || replicaRole == FABRIC_REPLICA_ROLE_NONE);
            }

            KAllocator & allocator = underlyingSystem_->PagedAllocator();

            KString::SPtr backupFolderPath = KPath::CreatePath(backupFolder.c_str(), allocator);
            TestBackupCallbackHandler::SPtr backupCallbackHandler = TestBackupCallbackHandler::Create(
                *backupFolderPath,
                allocator);

            Data::Utilities::OperationData::SPtr initParams = Data::Utilities::OperationData::Create(allocator);
            Data::Utilities::BinaryWriter bw(allocator);
            bw.Write(L"Initial Value", Data::Utilities::UTF16);
            initParams->Append(*bw.GetBuffer(0));

            {
                // Setting min log size in MB to 200 to avoid truncation of the log.
                TRANSACTIONAL_REPLICATOR_SETTINGS txnReplicatorSettings = { 0 };
                txnReplicatorSettings.Flags = FABRIC_TRANSACTIONAL_REPLICATOR_CHECKPOINT_THRESHOLD_MB;
                txnReplicatorSettings.CheckpointThresholdInMB = 200;

                Replica::SPtr replica = Replica::Create(
                    sourcePartitionId,
                    sourceReplicaID,
                    workFolder,
                    logManager,
                    allocator,
                    nullptr,
                    &txnReplicatorSettings);

                co_await replica->OpenAsync();

                // Become Primary after open:
                // 1. Update Status: Pending
                // 2. New Epoch with new data loss number.
                // 3. Change Role to Primary
                // 4. Update Status: Granted.
                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_RECONFIGURATION_PENDING);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_RECONFIGURATION_PENDING);

                FABRIC_EPOCH epoch1; epoch1.DataLossNumber = 1; epoch1.ConfigurationNumber = 1; epoch1.Reserved = nullptr;
                co_await replica->ChangeRoleAsync(epoch1, FABRIC_REPLICA_ROLE_PRIMARY);

                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_GRANTED);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_GRANTED);

                // Full backup
                {
                    BackupInfo fullBackupInfo;
                    status = co_await replica->TxnReplicator->BackupAsync(*backupCallbackHandler, fullBackupInfo);
                    VERIFY_IS_TRUE(NT_SUCCESS(status));
                }

                // Workload to increase the potential race gap.
                // Note that due to the optimization in the incremental backup path, this became a hard race.
                for (int i = 0; i < numberOfStateProviders; ++i)
                {
                    Transaction::SPtr txn;
                    replica->TxnReplicator->CreateTransaction(txn);
                    KFinally([&] {txn->Dispose(); });

                    KUri::CSPtr stateProviderName = GetStateProviderName(i);
                    status = co_await replica->TxnReplicator->AddAsync(
                        *txn,
                        *stateProviderName,
                        L"StoreType",
                        initParams.RawPtr());
                    VERIFY_IS_TRUE(NT_SUCCESS(status));
                    co_await txn->CommitAsync();
                }

                KArray<Awaitable<NTSTATUS>> awaitableArray(allocator);
                for (int i = 0; i < numberOfStateProviders; ++i)
                {
                    KUri::CSPtr stateProviderName = GetStateProviderName(i);
                    Data::TStore::IStore<int, int>::SPtr store;
                    status = GetStore<int, int>(*replica->TxnReplicator, *stateProviderName, store);
                    VERIFY_IS_TRUE(NT_SUCCESS(status));

                    Awaitable<NTSTATUS> awaitable = PopulateAsync(*underlyingSystem_, *replica->TxnReplicator, *store, 0, numberOfTxnPerSP, numberOfOperationPerTxn);
                    status = awaitableArray.Append(Ktl::Move(awaitable));
                    VERIFY_IS_TRUE(NT_SUCCESS(status));
                }

                status = co_await Data::Utilities::TaskUtilities<NTSTATUS>::WhenAll_NoException(awaitableArray);
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                // Incremental backup before the test incremental backup to increase the range.
                {
                    BackupInfo incrementalBackupInfo;
                    status = co_await replica->TxnReplicator->BackupAsync(
                        *backupCallbackHandler,
                        FABRIC_BACKUP_OPTION_INCREMENTAL,
                        Common::TimeSpan::FromMinutes(4),
                        CancellationToken::None,
                        incrementalBackupInfo);
                    VERIFY_IS_TRUE(NT_SUCCESS(status));
                }

                // Setup the backup handler so that we can block it.
                AwaitableCompletionSource<void>::SPtr acs;
                status = AwaitableCompletionSource<void>::Create(allocator, KTL_TAG_TEST, acs);
                VERIFY_IS_TRUE(NT_SUCCESS(status));
                backupCallbackHandler->SetBackupCallbackACS(*acs);

                // The test backup call.
                BackupInfo backupInfo;
                Awaitable<NTSTATUS> backupAwaitable = replica->TxnReplicator->BackupAsync(
                    *backupCallbackHandler,
                    FABRIC_BACKUP_OPTION_INCREMENTAL,
                    Common::TimeSpan::FromMinutes(4),
                    CancellationToken::None,
                    backupInfo);
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_NOT_PRIMARY);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_NOT_PRIMARY);

                // Racing change role to none.
                Awaitable<void> racingAwaitable;
                if (immediatelyClose == false)
                {
                    FABRIC_EPOCH epoch2; epoch2.DataLossNumber = 1; epoch2.ConfigurationNumber = 2; epoch2.Reserved = nullptr;
                    racingAwaitable = replica->ChangeRoleAsync(epoch2, replicaRole);
                }
                else
                {
                    racingAwaitable = replica->CloseAsync();
                }

                VERIFY_IS_FALSE(racingAwaitable.IsComplete());
                VERIFY_IS_FALSE(backupAwaitable.IsComplete());

                acs->Set();

                co_await racingAwaitable;

                // Test that backup has been drained.
                status = co_await backupAwaitable;
                VERIFY_ARE_EQUAL(SF_STATUS_NOT_PRIMARY, status);

                if (immediatelyClose != true)
                {
                    if (replicaRole != FABRIC_REPLICA_ROLE_NONE)
                    {
                        FABRIC_EPOCH epoch3; epoch3.DataLossNumber = 1; epoch3.ConfigurationNumber = 3; epoch3.Reserved = nullptr;
                        co_await replica->ChangeRoleAsync(epoch3, FABRIC_REPLICA_ROLE_NONE);
                    }

                    co_await replica->CloseAsync();
                }
            }

            if (immediatelyClose == true)
            {
                // Setting min log size in MB to 200 to avoid truncation of the log.
                TRANSACTIONAL_REPLICATOR_SETTINGS txnReplicatorSettings = { 0 };
                txnReplicatorSettings.Flags = FABRIC_TRANSACTIONAL_REPLICATOR_CHECKPOINT_THRESHOLD_MB;
                txnReplicatorSettings.CheckpointThresholdInMB = 200;

                Replica::SPtr replica = Replica::Create(
                    sourcePartitionId,
                    sourceReplicaID,
                    workFolder,
                    logManager,
                    allocator,
                    nullptr,
                    &txnReplicatorSettings);

                co_await replica->OpenAsync();

                FABRIC_EPOCH epoch4; epoch4.DataLossNumber = 1; epoch4.ConfigurationNumber = 4; epoch4.Reserved = nullptr;
                co_await replica->ChangeRoleAsync(epoch4, FABRIC_REPLICA_ROLE_NONE);

                co_await replica->CloseAsync();
            }

            co_return;
        }

        bool BackupTests::IsSameReplica(
            __in KGuid const & sourcePartitionId,
            __in FABRIC_REPLICA_ID sourceReplicaID,
            __in KGuid const & targetPartitionId,
            __in FABRIC_REPLICA_ID targetReplicaID)
        {
            return sourcePartitionId == targetPartitionId && sourceReplicaID == targetReplicaID;
        }

        template<class TKey, class TValue>
        NTSTATUS BackupTests::GetStore(
            __in ITransactionalReplicator & replicator,
            __in KUri const & stateProviderName,
            __out typename Data::TStore::IStore<TKey, TValue>::SPtr & store)
        {
            NTSTATUS status = STATUS_UNSUCCESSFUL;

            TxnReplicator::IStateProvider2::SPtr stateProvider;
            status = replicator.Get(stateProviderName, stateProvider);
            RETURN_ON_FAILURE(status);

            store = &dynamic_cast<Data::TStore::IStore<TKey, TValue> &>(*stateProvider);
            return status;
        }

        Awaitable<NTSTATUS> BackupTests::PopulateAsync(
            __in KtlSystem & system,
            __in ITransactionalReplicator & replicator,
            __in Data::TStore::IStore<int, int> & store,
            __in int startingKey,
            __in int numberOfTxns,
            __in int numberOfOperationsPerTxn) noexcept
        {
            NTSTATUS status = STATUS_UNSUCCESSFUL;

            co_await ktl::CorHelper::ThreadPoolThread(system.DefaultThreadPool());

            int currentKey = startingKey;

            for (int i = 0; i < numberOfTxns; ++i)
            {
                Transaction::SPtr txn;
                status = replicator.CreateTransaction(txn);
                CO_RETURN_ON_FAILURE(status);

                KFinally([txn] {txn->Dispose(); });

                Data::TStore::IStoreTransaction<int, int>::SPtr storeTxn;
                store.CreateOrFindTransaction(*txn, storeTxn);

                for (int opIndex = 0; opIndex < numberOfOperationsPerTxn; ++opIndex)
                {
                    co_await store.AddAsync(*storeTxn, currentKey, currentKey, TimeSpan::FromSeconds(4), CancellationToken::None);
                    currentKey++;
                }

                status = co_await txn->CommitAsync();
                CO_RETURN_ON_FAILURE(status);
            }

            co_return status;
        }

        wstring BackupTests::CreateFileName(
            __in wstring const & folderName)
        {
            wstring testFolderPath = Directory::GetCurrentDirectoryW();
            Path::CombineInPlace(testFolderPath, folderName);

            return testFolderPath;
        }

        void BackupTests::EndTest()
        {
        }

        void BackupTests::VerifyStateProviderExists(
            __in ITransactionalReplicator & replicator,
            __in KUri const & stateProviderName)
        {
            NTSTATUS status;

            IStateProvider2::SPtr stateProvider;
            status = replicator.Get(stateProviderName, stateProvider);
            VERIFY_IS_TRUE(NT_SUCCESS(status));
            VERIFY_IS_NOT_NULL(stateProvider);
        }

        void BackupTests::InitializeKtlConfig(
            __in std::wstring workDir,
            __in std::wstring fileName,
            __in KAllocator & allocator,
            __out KtlLogger::SharedLogSettingsSPtr & sharedLogSettings)
        {
            auto settings = std::make_unique<KtlLogManager::SharedLogContainerSettings>();

            KString::SPtr sharedLogFileName = KPath::CreatePath(workDir.c_str(), allocator);
            KPath::CombineInPlace(*sharedLogFileName, fileName.c_str());

            if (!Common::Directory::Exists(workDir))
            {
                Common::Directory::Create(workDir);
            }

            KInvariant(sharedLogFileName->LengthInBytes() + sizeof(WCHAR) < 512 * sizeof(WCHAR)); // check to make sure there is space for the null terminator
            KMemCpySafe(&settings->Path[0], 512 * sizeof(WCHAR), sharedLogFileName->operator PVOID(), sharedLogFileName->LengthInBytes());
            settings->Path[sharedLogFileName->LengthInBytes() / sizeof(WCHAR)] = L'\0'; // set the null terminator
            settings->LogContainerId.GetReference().CreateNew();
            settings->LogSize = 1024 * 1024 * 512; // 512 MB.
            settings->MaximumNumberStreams = 0;
            settings->MaximumRecordSize = 0;
            settings->Flags = static_cast<ULONG>(Data::Log::LogCreationFlags::UseSparseFile);
            sharedLogSettings = make_shared<KtlLogger::SharedLogSettings>(std::move(settings));
        };

        KUri::CSPtr BackupTests::GetStateProviderName(
            __in int stateProviderIndex)
        {
            wstring stateProviderName = wformatString(L"fabric:/store/{0}", stateProviderIndex);

            KUri::CSPtr spName;
            NTSTATUS status = KUri::Create(KStringView(stateProviderName.c_str()), underlyingSystem_->PagedAllocator(), spName);
            if (NT_SUCCESS(status) == false)
            {
                throw Exception(status);
            }

            return spName;
        }

        BOOST_FIXTURE_TEST_SUITE(BackupTestSuite, BackupTests);

        BOOST_AUTO_TEST_CASE(Restore_Full_SameReplica_Success)
        {
            // Setup
            wstring testName(L"Restore_Full_SameReplica_Success");
            wstring testFolderPath = CreateFileName(testName);

            // Start up cleanup.
            Directory::Delete_WithRetry(testFolderPath, true, true);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = Path::Combine(testFolderPath, L"backup");

            TEST_TRACE_BEGIN(testName)
            {
                // KTL test input
                KGuid sourcePartitionId;
                sourcePartitionId.CreateNew();
                FABRIC_REPLICA_ID const sourceReplicaId = 777;

                // Test Setup
                KtlLogger::SharedLogSettingsSPtr sharedLogSettings;
                InitializeKtlConfig(testFolderPath, TestLogFileName, underlyingSystem_->NonPagedAllocator(), sharedLogSettings);

                Data::Log::LogManager::SPtr logManager;
                status = Data::Log::LogManager::Create(underlyingSystem_->NonPagedAllocator(), logManager);
                CODING_ERROR_ASSERT(NT_SUCCESS(status));

                status = SyncAwait(logManager->OpenAsync(CancellationToken::None, sharedLogSettings));
                CODING_ERROR_ASSERT(NT_SUCCESS(status));

                // Test call
                SyncAwait(Test_RestoreIncremental(
                    workFolder,
                    backupFolder,
                    16,
                    32,
                    1,
                    *logManager,
                    sourcePartitionId,
                    sourceReplicaId,
                    sourcePartitionId,
                    sourceReplicaId,
                    FABRIC_RESTORE_POLICY_FORCE));

                status = SyncAwait(logManager->CloseAsync(CancellationToken::None));
                CODING_ERROR_ASSERT(NT_SUCCESS(status));
                logManager = nullptr;
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        BOOST_AUTO_TEST_CASE(Restore_Full_DifferentTargetPartition_Success)
        {
            // Setup
            wstring testName(L"Restore_Full_DifferentTargetPartition_Success");
            wstring testFolderPath = CreateFileName(testName);

            // Start up cleanup.
            Directory::Delete_WithRetry(testFolderPath, true, true);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = Path::Combine(testFolderPath, L"backup");

            TEST_TRACE_BEGIN(testName)
            {
                // KTL test input
                KGuid sourcePartitionId;
                sourcePartitionId.CreateNew();
                FABRIC_REPLICA_ID sourceReplicaId = 777;

                KGuid targetPartitionId;
                targetPartitionId.CreateNew();
                FABRIC_REPLICA_ID targetReplicaId = 555;

                KtlLogger::SharedLogSettingsSPtr sharedLogSettings;
                InitializeKtlConfig(testFolderPath, TestLogFileName, underlyingSystem_->NonPagedAllocator(), sharedLogSettings);

                Data::Log::LogManager::SPtr logManager;
                status = Data::Log::LogManager::Create(underlyingSystem_->NonPagedAllocator(), logManager);
                CODING_ERROR_ASSERT(NT_SUCCESS(status));

                status = SyncAwait(logManager->OpenAsync(CancellationToken::None, sharedLogSettings));
                CODING_ERROR_ASSERT(NT_SUCCESS(status));

                SyncAwait(Test_RestoreIncremental(
                    workFolder,
                    backupFolder,
                    16,
                    32,
                    1,
                    *logManager,
                    sourcePartitionId,
                    sourceReplicaId,
                    targetPartitionId,
                    targetReplicaId,
                    FABRIC_RESTORE_POLICY_SAFE));

                status = SyncAwait(logManager->CloseAsync(CancellationToken::None));
                CODING_ERROR_ASSERT(NT_SUCCESS(status));
                logManager = nullptr;
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        BOOST_AUTO_TEST_CASE(Restore_Incremental_SameReplica_Success)
        {
            // Setup
            wstring testName(L"Restore_Incremental_SameReplica_Success");
            wstring testFolderPath = CreateFileName(testName);

            // Start up cleanup.
            Directory::Delete_WithRetry(testFolderPath, true, true);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = Path::Combine(testFolderPath, L"backup");

            TEST_TRACE_BEGIN(testName)
            {
                // KTL test input
                KGuid sourcePartitionId;
                sourcePartitionId.CreateNew();
                FABRIC_REPLICA_ID sourceReplicaId = 777;

                KtlLogger::SharedLogSettingsSPtr sharedLogSettings;
                InitializeKtlConfig(testFolderPath, TestLogFileName, underlyingSystem_->NonPagedAllocator(), sharedLogSettings);

                Data::Log::LogManager::SPtr logManager;
                status = Data::Log::LogManager::Create(underlyingSystem_->NonPagedAllocator(), logManager);
                CODING_ERROR_ASSERT(NT_SUCCESS(status));

                status = SyncAwait(logManager->OpenAsync(CancellationToken::None, sharedLogSettings));
                CODING_ERROR_ASSERT(NT_SUCCESS(status));

                SyncAwait(Test_RestoreIncremental(
                    workFolder,
                    backupFolder,
                    16,
                    16,
                    4,
                    *logManager,
                    sourcePartitionId,
                    sourceReplicaId,
                    sourcePartitionId,
                    sourceReplicaId,
                    FABRIC_RESTORE_POLICY_FORCE));

                status = SyncAwait(logManager->CloseAsync(CancellationToken::None));
                CODING_ERROR_ASSERT(NT_SUCCESS(status));
                logManager = nullptr;
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        BOOST_AUTO_TEST_CASE(Restore_Incremental_DifferentTargetPartition_Success)
        {
            // Setup
            wstring testName(L"Restore_Incremental_DifferentTargetPartition_Success");
            wstring testFolderPath = CreateFileName(testName);

            // Start up cleanup.
            Directory::Delete_WithRetry(testFolderPath, true, true);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = Path::Combine(testFolderPath, L"backup");

            TEST_TRACE_BEGIN(testName)
            {
                // KTL test input
                KGuid sourcePartitionId;
                sourcePartitionId.CreateNew();
                FABRIC_REPLICA_ID sourceReplicaId = 777;

                KGuid targetPartitionId;
                targetPartitionId.CreateNew();
                FABRIC_REPLICA_ID targetReplicaId = 555;

                KtlLogger::SharedLogSettingsSPtr sharedLogSettings;
                InitializeKtlConfig(testFolderPath, TestLogFileName, underlyingSystem_->NonPagedAllocator(), sharedLogSettings);

                Data::Log::LogManager::SPtr logManager;
                status = Data::Log::LogManager::Create(underlyingSystem_->NonPagedAllocator(), logManager);
                CODING_ERROR_ASSERT(NT_SUCCESS(status));

                status = SyncAwait(logManager->OpenAsync(CancellationToken::None, sharedLogSettings));
                CODING_ERROR_ASSERT(NT_SUCCESS(status));

                SyncAwait(Test_RestoreIncremental(
                    workFolder,
                    backupFolder,
                    16,
                    16,
                    4,
                    *logManager,
                    sourcePartitionId,
                    sourceReplicaId,
                    targetPartitionId,
                    targetReplicaId,
                    FABRIC_RESTORE_POLICY_SAFE));

                status = SyncAwait(logManager->CloseAsync(CancellationToken::None));
                CODING_ERROR_ASSERT(NT_SUCCESS(status));
                logManager = nullptr;
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        BOOST_AUTO_TEST_CASE(Backup_ConcurrentClose_WithoutOperations_DrainTheBackup)
        {
            int const StateProviderCount = 0;
            int const NumberOfTxnPerSP = 0;
            int const NumberOfOpPerTxn = 0;

            // Setup
            wstring testName(L"Backup_ConcurrentClose_WithoutOperations_DrainTheBackup");
            wstring testFolderPath = CreateFileName(testName);

            // Start up cleanup.
            Directory::Delete_WithRetry(testFolderPath, true, true);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = Path::Combine(testFolderPath, L"backup");

            TEST_TRACE_BEGIN(testName)
            {
                SyncAwait(Run_Backup_Concurency_Backup_ChangeRoleOrClose_DrainTheBackup(
                    workFolder,
                    backupFolder,
                    testFolderPath,
                    StateProviderCount,
                    NumberOfTxnPerSP,
                    NumberOfOpPerTxn,
                    true,
                    FABRIC_REPLICA_ROLE_UNKNOWN));
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        BOOST_AUTO_TEST_CASE(Backup_ConcurrentClose_WithOperations_DrainTheBackup)
        {
            int const StateProviderCount = 8;
            int const NumberOfTxnPerSP = 8;
            int const NumberOfOpPerTxn = 8;

            // Setup
            wstring testName(L"Backup_ConcurrentClose_WithOperations_DrainTheBackup");
            wstring testFolderPath = CreateFileName(testName);

            // Start up cleanup.
            Directory::Delete_WithRetry(testFolderPath, true, true);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = Path::Combine(testFolderPath, L"backup");

            TEST_TRACE_BEGIN(testName)
            {
                SyncAwait(Run_Backup_Concurency_Backup_ChangeRoleOrClose_DrainTheBackup(
                    workFolder,
                    backupFolder,
                    testFolderPath,
                    StateProviderCount,
                    NumberOfTxnPerSP,
                    NumberOfOpPerTxn,
                    true,
                    FABRIC_REPLICA_ROLE_UNKNOWN));
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        BOOST_AUTO_TEST_CASE(Backup_Concurency_Backup_ChangeRoleToSecondary_DrainTheBackup)
        {
            int const StateProviderCount = 8;
            int const NumberOfTxnPerSP = 8;
            int const NumberOfOpPerTxn = 8;

            // Setup
            wstring testName(L"Backup_Concurency_Backup_ChangeRoleToSecondary_DrainTheBackup");
            wstring testFolderPath = CreateFileName(testName);

            // Start up cleanup.
            Directory::Delete_WithRetry(testFolderPath, true, true);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = Path::Combine(testFolderPath, L"backup");

            TEST_TRACE_BEGIN(testName)
            {
                SyncAwait(Run_Backup_Concurency_Backup_ChangeRoleOrClose_DrainTheBackup(
                    workFolder,
                    backupFolder,
                    testFolderPath,
                    StateProviderCount,
                    NumberOfTxnPerSP,
                    NumberOfOpPerTxn,
                    false,
                    FABRIC_REPLICA_ROLE_ACTIVE_SECONDARY));
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        BOOST_AUTO_TEST_CASE(Backup_Concurency_Backup_ChangeRoleToNone_DrainTheBackup)
        {
            int const StateProviderCount = 8;
            int const NumberOfTxnPerSP = 8;
            int const NumberOfOpPerTxn = 8;

            // Setup
            wstring testName(L"Backup_Concurency_Backup_ChangeRoleToNone_DrainTheBackup");
            wstring testFolderPath = CreateFileName(testName);

            // Start up cleanup.
            Directory::Delete_WithRetry(testFolderPath, true, true);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = Path::Combine(testFolderPath, L"backup");

            TEST_TRACE_BEGIN(testName)
            {
                SyncAwait(Run_Backup_Concurency_Backup_ChangeRoleOrClose_DrainTheBackup(
                    workFolder,
                    backupFolder,
                    testFolderPath,
                    StateProviderCount,
                    NumberOfTxnPerSP,
                    NumberOfOpPerTxn,
                    false,
                    FABRIC_REPLICA_ROLE_NONE));
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        BOOST_AUTO_TEST_SUITE_END();
    }
}

ext: cpp


text:
/*
 * $Id: vecio.cc 1414 2005-11-01 22:04:59Z cookedm $
 *
 * Copyright (C) 1997 Todd Veldhuizen <tveldhui@oonumerics.org>
 * All rights reserved.  Please see <blitz/blitz.h> for terms and
 * conditions of use.
 *
 */

#ifndef BZ_VECIO_CC
#define BZ_VECIO_CC

#ifndef BZ_VECTOR_H
 #include <blitz/vector.h>
#endif

BZ_NAMESPACE(blitz)

// This version of operator<< is provided as a temporary measure
// only.  It will be revised in a future release.
// NEEDS_WORK

template<typename P_numtype>
ostream& operator<<(ostream& os, const Vector<P_numtype>& x)
{
    os << "[ ";
    for (int i=0; i < x.length(); ++i)
    {
        os << setw(10) << x[i];
        if (!((i+1)%7))
            os << endl << "  ";
    }
    os << " ]";
    return os;
}

template<typename P_expr>
ostream& operator<<(ostream& os, _bz_VecExpr<P_expr> expr)
{
    Vector<_bz_typename P_expr::T_numtype> result(expr);
    os << result;
    return os;
}

BZ_NAMESPACE_END

#endif // BZ_VECIO_CC

ext: cc

max_stars_repo_name: lefevre-fraser/openmeta-mms

max_issues_repo_name: lefevre-fraser/openmeta-mms

max_forks_repo_name: lefevre-fraser/openmeta-mms


text:
#include <ros/ros.h>
#include <pluginlib/class_list_macros.h>
#include <hardware_interface/joint_command_interface.h>
#include <hardware_interface/robot_hw.h>
#include <gazebo/common/common.hh>
#include <gazebo/physics/physics.hh>
#include <gazebo/gazebo.hh>
#include <angles/angles.h>
#include <gazebo_ros_control/robot_hw_sim.h>
#include <urdf/model.h>
#include <boost/assign/list_of.hpp>
#include <boost/foreach.hpp>

namespace walrus_gazebo
{

typedef struct {
  double pos;
  double vel;
  double eff;
} JointState;

class WalrusBaseEposHWSim : public gazebo_ros_control::RobotHWSim
{
private:
  static std::vector<std::string> POD_POSITIONS;
  static std::vector<std::string> DRIVE_SIDES;
  static double MAX_DRIVE_TORQUE;

  std::vector<std::vector<gazebo::physics::JointPtr> > drive_joints;
  std::vector<std::vector<double> > drive_joint_multipliers;
  std::vector<double> drive_cmds;
  std::vector<JointState> drive_states;

  hardware_interface::JointStateInterface js_interface;
  hardware_interface::VelocityJointInterface vj_interface;

public:
  bool initSim(const std::string& robot_namespace, ros::NodeHandle model_nh, gazebo::physics::ModelPtr parent_model,
               const urdf::Model* const urdf_model, std::vector<transmission_interface::TransmissionInfo> transmissions)
  {
    std::string tf_prefix = "walrus/";

    // Load drive joints
    drive_cmds.resize(DRIVE_SIDES.size(), 0);
    drive_states.resize(DRIVE_SIDES.size());
    drive_joints.resize(DRIVE_SIDES.size());
    drive_joint_multipliers.resize(DRIVE_SIDES.size());
    for(int i = 0; i<DRIVE_SIDES.size(); ++i){
      const std::string& drive_name = DRIVE_SIDES[i];
      const std::string& drive_joint_name = tf_prefix+drive_name+"_drive_joint";

      // Enumerate joint names for the drive
      std::vector<std::string> joint_names;
      joint_names.push_back(drive_joint_name); // Driven joint must be first
      joint_names.push_back(tf_prefix+drive_name+"_drive_idler_joint");
      BOOST_FOREACH(const std::string& pod_position, POD_POSITIONS) {
	const std::string& pod_name = pod_position + "_" + drive_name;
	joint_names.push_back(tf_prefix+pod_name+"_pod_drive_joint");
	joint_names.push_back(tf_prefix+pod_name+"_pod_drive_idler_joint");
      }

      // Get drive joints
      BOOST_FOREACH(const std::string& joint_name, joint_names) {
	// Validate joint configuration
	gazebo::physics::JointPtr joint = parent_model->GetJoint(joint_name);
	if(!joint) {
	  ROS_FATAL_STREAM("Could not load joint: " << joint_name);
	  return false;
	}
	boost::shared_ptr<const urdf::Joint> urdf_joint = urdf_model->getJoint(joint_name);
	if(!urdf_joint) {
	  ROS_FATAL_STREAM("Could not load URDF joint: " << joint_name);
	  return false;
	}
	boost::shared_ptr<const urdf::JointMimic> joint_mimic = urdf_joint->mimic;
	if(drive_joints[i].empty() ^ !joint_mimic){
	  ROS_FATAL_STREAM("Drive joint mimic should be specified on all non-driven drive joints only: " << joint_name);
	  return false;
	}
	if(joint_mimic) {
	  if(joint_mimic->joint_name != drive_joint_name){
	    ROS_FATAL_STREAM("Drive joint mimic must refer to the driven joint: " << joint_name);
	    return false;
	  }
	  if(joint_mimic->multiplier == 0){
	    ROS_FATAL_STREAM("Drive joint mimic multiplier must not be 0: " << joint_name);
	    return false;
	  }
	  if(joint_mimic->offset != 0){
	    ROS_FATAL_STREAM("Drive joint mimic offset must be 0: " << joint_name);
	    return false;
	  }
	  drive_joint_multipliers[i].push_back(joint_mimic->multiplier);
	}
	else {
	  drive_joint_multipliers[i].push_back(1.0);
	}
	// Configure and store joint
	joint->SetMaxForce(0, MAX_DRIVE_TORQUE);
	drive_joints[i].push_back(joint);
      }

      js_interface.registerHandle(hardware_interface::JointStateHandle(drive_joint_name, &drive_states[i].pos, &drive_states[i].vel, &drive_states[i].eff));
      vj_interface.registerHandle(hardware_interface::JointHandle(js_interface.getHandle(drive_joint_name), &drive_cmds[i]));
    }

    registerInterface(&js_interface);
    registerInterface(&vj_interface);

    return true;
  }

  // Read state from the simulator
  void readSim(ros::Time time, ros::Duration period) {
    for(int i = 0; i<drive_joints.size(); ++i){
      gazebo::physics::JointPtr joint = drive_joints[i][0];//just use the first joint
      drive_states[i].pos += angles::shortest_angular_distance(drive_states[i].pos, joint->GetAngle(0).Radian());
      drive_states[i].vel = joint->GetVelocity(0);
      drive_states[i].eff = joint->GetForce((unsigned int)(0));
    }
  }

  // Write control to the simulator
  void writeSim(ros::Time time, ros::Duration period) {
    for(int i = 0; i<drive_joints.size(); ++i){
      for(int j = 0; j < drive_joints[i].size(); ++j){
	gazebo::physics::JointPtr joint = drive_joints[i][j];
	double multiplier = drive_joint_multipliers[i][j];
        joint->SetVelocity(0, drive_cmds[i] * multiplier);
      }
    }
  }

};

std::vector<std::string> WalrusBaseEposHWSim::POD_POSITIONS = boost::assign::list_of("front")("back");
std::vector<std::string> WalrusBaseEposHWSim::DRIVE_SIDES = boost::assign::list_of("left")("right");
double WalrusBaseEposHWSim::MAX_DRIVE_TORQUE = 1000;

}

PLUGINLIB_EXPORT_CLASS(walrus_gazebo::WalrusBaseEposHWSim, gazebo_ros_control::RobotHWSim)

max_stars_repo_name: RIVeR-Lab/walrus

max_issues_repo_name: RIVeR-Lab/walrus

max_forks_repo_name: RIVeR-Lab/walrus


text:
// Copyright (c) 2019 Duality Blockchain Solutions Developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "bdap/domainentry.h"

#include "base58.h"
#include "bdap/utils.h"
#include "rpc/client.h"
#include "rpc/server.h"
#include "primitives/block.h"
#include "txmempool.h"
#include "serialize.h"
#include "streams.h"
#include "validation.h"
#include "wallet/wallet.h"

#include <univalue.h>

#include <boost/algorithm/string/find.hpp>
#include <boost/xpressive/xpressive_dynamic.hpp>

using namespace boost::xpressive;

bool CDomainEntry::UnserializeFromTx(const CTransactionRef& tx) {
    std::vector<unsigned char> vchData;
    std::vector<unsigned char> vchHash;
    int nOut;
    if(!GetBDAPData(tx, vchData, vchHash, nOut))
    {
        SetNull();
        return false;
    }
    if(!UnserializeFromData(vchData, vchHash))
    {
        return false;
    }
    return true;
}

void CDomainEntry::Serialize(std::vector<unsigned char>& vchData) {
    CDataStream dsBDAP(SER_NETWORK, PROTOCOL_VERSION);
    dsBDAP << *this;
    vchData = std::vector<unsigned char>(dsBDAP.begin(), dsBDAP.end());
}

bool CDomainEntry::UnserializeFromData(const std::vector<unsigned char>& vchData, const std::vector<unsigned char>& vchHash) {
    try {
        CDataStream dsBDAP(vchData, SER_NETWORK, PROTOCOL_VERSION);
        dsBDAP >> *this;

        std::vector<unsigned char> vchBDAPData;
        Serialize(vchBDAPData);
        const uint256 &calculatedHash = Hash(vchBDAPData.begin(), vchBDAPData.end());
        const std::vector<unsigned char> &vchRandBDAP = vchFromValue(calculatedHash.GetHex());
        if(vchRandBDAP != vchHash)
        {
            SetNull();
            return false;
        }
    } catch (std::exception &e) {
        SetNull();
        return false;
    }
    return true;
}

CDynamicAddress CDomainEntry::GetWalletAddress() const {
    return CDynamicAddress(stringFromVch(WalletAddress));
}

CDynamicAddress CDomainEntry::GetLinkAddress() const {
    return CDynamicAddress(stringFromVch(LinkAddress));
}

std::string CDomainEntry::DHTPubKeyString() const {
    return stringFromVch(DHTPublicKey);
}

std::string CDomainEntry::GetFullObjectPath() const {
    return stringFromVch(ObjectID) + "@" + stringFromVch(OrganizationalUnit) + "." + stringFromVch(DomainComponent);
}

std::string CDomainEntry::GetObjectLocation() const {
    return stringFromVch(OrganizationalUnit) + "." + stringFromVch(DomainComponent);
}

std::vector<unsigned char> CDomainEntry::vchFullObjectPath() const {
    std::string strFullObjectPath = GetFullObjectPath();
    std::vector<unsigned char> vchReturnValue(strFullObjectPath.begin(), strFullObjectPath.end());
    return vchReturnValue;
}

std::vector<unsigned char> CDomainEntry::vchObjectLocation() const {
    std::string strObjectLocation = GetObjectLocation();
    std::vector<unsigned char> vchReturnValue(strObjectLocation.begin(), strObjectLocation.end());
    return vchReturnValue;
}

bool CDomainEntry::ValidateValues(std::string& errorMessage)
{
    smatch sMatch;
    std::string regExWithDot = "^((?!-)[a-z0-9-]{2," + std::to_string(MAX_OBJECT_NAME_LENGTH) + "}(?<!-)\\.)+[a-z]{2,6}$";
    std::string regExWithOutDot = "^((?!-)[a-z0-9-]{2," + std::to_string(MAX_OBJECT_NAME_LENGTH) + "}(?<!-))";

    // check domain name component
    std::string strDomainComponent = stringFromVch(DomainComponent);
    if (boost::find_first(strDomainComponent, "."))
    {
        sregex regexValidName = sregex::compile(regExWithDot);
        if (!regex_search(strDomainComponent, sMatch, regexValidName) || std::string(sMatch[0]) != strDomainComponent) {
            errorMessage = "Invalid BDAP domain name. Must follow the domain name spec of 2 to " + std::to_string(MAX_OBJECT_NAME_LENGTH) + " characters with no preceding or trailing dashes.";
            return false;
        }
    }
    else
    {
        sregex regexValidName = sregex::compile(regExWithOutDot);
        if (!regex_search(strDomainComponent, sMatch, regexValidName) || std::string(sMatch[0]) != strDomainComponent) {
            errorMessage = "Invalid BDAP domain name. Must follow the domain name spec of 2 to " + std::to_string(MAX_OBJECT_NAME_LENGTH) + " characters with no preceding or trailing dashes.";
            return false;
        }
    }

    // check organizational unit component
    std::string strOrganizationalUnit = stringFromVch(OrganizationalUnit);
    if (boost::find_first(strOrganizationalUnit, "."))
    {
        sregex regexValidName = sregex::compile(regExWithDot);
        if (!regex_search(strOrganizationalUnit, sMatch, regexValidName) || std::string(sMatch[0]) != strOrganizationalUnit) {
            errorMessage = "Invalid BDAP organizational unit. Must follow the domain name spec of 2 to " + std::to_string(MAX_OBJECT_NAME_LENGTH) + " characters with no preceding or trailing dashes.";
            return false;
        }
    }
    else
    {
        sregex regexValidName = sregex::compile(regExWithOutDot);
        if (!regex_search(strOrganizationalUnit, sMatch, regexValidName) || std::string(sMatch[0]) != strOrganizationalUnit) {
            errorMessage = "Invalid BDAP organizational unit. Must follow the domain name spec of 2 to " + std::to_string(MAX_OBJECT_NAME_LENGTH) + " characters with no preceding or trailing dashes.";
            return false;
        }
    }

    // check object name component
    std::string strObjectID = stringFromVch(ObjectID);
    if (boost::find_first(strObjectID, "."))
    {
        sregex regexValidName = sregex::compile(regExWithDot);
        if (!regex_search(strObjectID, sMatch, regexValidName) || std::string(sMatch[0]) != strObjectID) {
            errorMessage = "Invalid BDAP object name. Must follow the domain name spec of 2 to " + std::to_string(MAX_OBJECT_NAME_LENGTH) + " characters with no preceding or trailing dashes.";
            return false;
        }
    }
    else
    {
        sregex regexValidName = sregex::compile(regExWithOutDot);
        if (!regex_search(strObjectID, sMatch, regexValidName) || std::string(sMatch[0]) != strObjectID) {
            errorMessage = "Invalid BDAP object name. Must follow the domain name spec of 2 to " + std::to_string(MAX_OBJECT_NAME_LENGTH) + " characters with no preceding or trailing dashes.";
            return false;
        }
    }

    // check object common name component
    if (CommonName.size() > MAX_COMMON_NAME_LENGTH)
    {
        errorMessage = "Invalid BDAP common name. Can not have more than " + std::to_string(MAX_COMMON_NAME_LENGTH) + " characters.";
        return false;
    }

    // check object organization name component
    if (OrganizationName.size() > MAX_ORG_NAME_LENGTH)
    {
        errorMessage = "Invalid BDAP organization name. Can not have more than " + std::to_string(MAX_ORG_NAME_LENGTH) + " characters.";
        return false;
    }

    if (WalletAddress.size() > MAX_WALLET_ADDRESS_LENGTH)
    {
        errorMessage = "Invalid BDAP wallet address. Can not have more than " + std::to_string(MAX_WALLET_ADDRESS_LENGTH) + " characters.";
        return false;
    }
    else {
        std::string strWalletAddress = stringFromVch(WalletAddress);
        CDynamicAddress entryAddress(strWalletAddress);
        if (!entryAddress.IsValid()) {
            errorMessage = "Invalid BDAP wallet address. Wallet address failed IsValid check.";
            return false;
        }
    }

    if (LinkAddress.size() > MAX_WALLET_ADDRESS_LENGTH)
    {
        errorMessage = "Invalid BDAP link address. Can not have more than " + std::to_string(MAX_WALLET_ADDRESS_LENGTH) + " characters.";
        return false;
    }
    else {
        if (LinkAddress.size() > 0) {
            std::string strLinkAddress = stringFromVch(LinkAddress);
            CTxDestination destLink = DecodeDestination(strLinkAddress);
            if (destLink.type() == typeid(CKeyID)) {
                CDynamicAddress entryLinkAddress(strLinkAddress);
                if (!entryLinkAddress.IsValid()) {
                    errorMessage = "Invalid BDAP public link address. Link wallet address failed IsValid check.";
                    return false;
                }
            }
            else if (destLink.type() == typeid(CStealthAddress)) {
                CStealthAddress sxAddr;
                if (!sxAddr.SetEncoded(strLinkAddress)) {
                    errorMessage = "Invalid BDAP stealth link address. Link wallet address failed SetEncoded check.";
                    return false;
                }
            }
        }
    }

    if (DHTPublicKey.size() > MAX_KEY_LENGTH)
    {
        errorMessage = "Invalid BDAP encryption public key. Can not have more than " + std::to_string(MAX_KEY_LENGTH) + " characters.";
        return false;
    }
    //TODO (BDAP): validate Ed25519 public key if possible.
    /*
    else {
        if (DHTPublicKey.size() > 0) {
            CPubKey entryDHTPublicKey(DHTPublicKey);
            if (!entryDHTPublicKey.IsFullyValid()) {
                errorMessage = "Invalid BDAP encryption public key. Encryption public key failed IsFullyValid check.";
                return false;
            }
        }
    }
    */
    return true;
}

/** Checks if BDAP transaction exists in the memory pool */
bool CDomainEntry::CheckIfExistsInMemPool(const CTxMemPool& pool, std::string& errorMessage)
{
    for (const CTxMemPoolEntry& e : pool.mapTx) {
        const CTransactionRef& tx = e.GetSharedTx();
        for (const CTxOut& txOut : tx->vout) {
            if (IsBDAPDataOutput(txOut)) {
                CDomainEntry domainEntry(tx);
                if (this->GetFullObjectPath() == domainEntry.GetFullObjectPath()) {
                    errorMessage = "CheckIfExistsInMemPool: A BDAP domain entry transaction for " + GetFullObjectPath() + " is already in the memory pool!";
                    return true;
                }
            }
        }
    }
    return false;
}

/** Checks if the domain entry transaction uses the entry's UTXO */
bool CDomainEntry::TxUsesPreviousUTXO(const CTransactionRef& tx)
{
    int nIn = GetBDAPOperationOutIndex(tx);
    COutPoint entryOutpoint = COutPoint(txHash, nIn);
    for (const CTxIn& txIn : tx->vin) {
        if (txIn.prevout == entryOutpoint)
            return true;
    }
    return false;
}

/** Generate unique OID when using the root BDAP OID prefix */
std::string CDomainEntry::GenerateOID() const
{
    std::string strOID;
    if (RootOID == vchDefaultOIDPrefix)
    {
        // BDAP generated OID: 2.16.840.1.114564.block-height.tx-ordinal
        std::string strTxOrdinal = "?";
        std::string strHeight = "?";
        if (nHeight > 0)
        {
            strHeight = std::to_string(nHeight);
        }
        if (!txHash.IsNull() && !IsInitialBlockDownload())
        {
            CTransactionRef txRef;
            uint256 hashBlock;
            const Consensus::Params& consensusParams = Params().GetConsensus();
            if (GetTransaction(txHash, txRef, consensusParams, hashBlock, true))
            {
                if (!hashBlock.IsNull())
                {
                    CBlock block;
                    CBlockIndex* pblockindex = mapBlockIndex[hashBlock];
                    if (pblockindex && ReadBlockFromDisk(block, pblockindex, consensusParams))
                    {
                        int nTxOrdinal = 0;
                        for (const auto& tx : block.vtx) {
                            if (tx->GetHash() == txHash)
                            {
                                strTxOrdinal = std::to_string(nTxOrdinal);
                                break;
                            }
                            nTxOrdinal++;
                        }
                    }
                }
            }
        }
        strOID = strprintf("%s.%s.%s", stringFromVch(RootOID), strHeight, strTxOrdinal);
    }
    else
    {
        strOID = stringFromVch(RootOID);
    }
    return strOID;
}

bool BuildBDAPJson(const CDomainEntry& entry, UniValue& oName, bool fAbridged)
{
    bool expired = false;
    int64_t expired_time = 0;
    int64_t nTime = 0;
    if (!fAbridged) {
        oName.push_back(Pair("oid", entry.GenerateOID()));
        oName.push_back(Pair("version", entry.nVersion));
        oName.push_back(Pair("domain_component", stringFromVch(entry.DomainComponent)));
        oName.push_back(Pair("common_name", stringFromVch(entry.CommonName)));
        oName.push_back(Pair("organizational_unit", stringFromVch(entry.OrganizationalUnit)));
        oName.push_back(Pair("organization_name", stringFromVch(entry.DomainComponent)));
        oName.push_back(Pair("object_id", stringFromVch(entry.ObjectID)));
        oName.push_back(Pair("object_full_path", entry.GetFullObjectPath()));
        oName.push_back(Pair("object_type", entry.ObjectTypeString()));
        oName.push_back(Pair("wallet_address", stringFromVch(entry.WalletAddress)));
        oName.push_back(Pair("public", (int)entry.fPublicObject));
        oName.push_back(Pair("dht_publickey", stringFromVch(entry.DHTPublicKey)));
        oName.push_back(Pair("link_address", stringFromVch(entry.LinkAddress)));
        oName.push_back(Pair("txid", entry.txHash.GetHex()));
        if ((unsigned int)chainActive.Height() >= entry.nHeight-1) {
            CBlockIndex *pindex = chainActive[entry.nHeight-1];
            if (pindex) {
                nTime = pindex->GetMedianTimePast();
            }
        }
        oName.push_back(Pair("time", nTime));
        //oName.push_back(Pair("height", entry.nHeight));
        expired_time = entry.nExpireTime;
        if(expired_time <= (unsigned int)chainActive.Tip()->GetMedianTimePast())
        {
            expired = true;
        }
        oName.push_back(Pair("expires_on", expired_time));
        oName.push_back(Pair("expired", expired));
    }
    else {
        oName.push_back(Pair("common_name", stringFromVch(entry.CommonName)));
        oName.push_back(Pair("object_full_path", stringFromVch(entry.vchFullObjectPath())));
        oName.push_back(Pair("wallet_address", stringFromVch(entry.WalletAddress)));
        oName.push_back(Pair("dht_publickey", stringFromVch(entry.DHTPublicKey)));
        oName.push_back(Pair("link_address", stringFromVch(entry.LinkAddress)));
        oName.push_back(Pair("object_type", entry.ObjectTypeString()));
    }
    return true;
}

max_stars_repo_name: LordDarkHelmet/Dynamic

max_issues_repo_name: LordDarkHelmet/Dynamic

max_forks_repo_name: LordDarkHelmet/Dynamic


text:
// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_PROGRAM_OPTIONS_2_FWD_HPP
#define BOOST_PROGRAM_OPTIONS_2_FWD_HPP

#include <boost/program_options_2/config.hpp>
#include <boost/program_options_2/tag_invoke.hpp>

#include <boost/any.hpp>

// Silence very verbose warnings about std::is_pod being deprecated.  TODO:
// Remove this if/when Hana accepts releases the fix for this (already on
// develop).
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#include <boost/hana.hpp>
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop
#endif

#include <any>
#include <array>
#include <map>
#include <string_view>
#include <type_traits>

namespace boost { namespace program_options_2 {

    /** TODO */
    inline constexpr int zero_or_one = -1;
    /** TODO */
    inline constexpr int zero_or_more = -2;
    /** TODO */
    inline constexpr int one_or_more = -3;

    /** TODO */
    struct customizable_strings
    {
        std::string_view usage_text = "usage: ";
        std::string_view positional_section_text = "positional arguments:";
        std::string_view optional_section_text = "optional arguments:";
        std::string_view help_names = "-h,--help";
        std::string_view help_description = "Print this help message and exit";
        std::string_view response_file_description =
            "response files:\n  Write '@file' to load a file containing "
            "command line arguments.";

        std::array<std::string_view, 6> parse_errors = {
            {"error: unrecognized argument '{}'",
             "error: wrong number of arguments for '{}'",
             "error: cannot parse argument '{}'",
             "error: '{}' is not one of the allowed choices",
             "error: unexpected positional argument '{}'",
             "error: one or more missing positional arguments, starting with "
             "'{}'"}};

        // validation errors
        std::string_view path_not_found = "error: path '{}' not found";
        std::string_view file_not_found = "error: file '{}' not found";
        std::string_view directory_not_found =
            "error: directory '{}' not found";
        std::string_view found_file_not_directory =
            "error: '{}' is a file, but a directory was expected";
        std::string_view found_directory_not_file =
            "error: '{}' is a directory, but a file was expected";
        std::string_view cannot_read = "error: cannot open '{}' for reading";
    };

    /** TODO */
    struct validation_result
    {
        bool valid = true;
        std::string_view error;
    };

    /** TODO */
    struct no_value
    {};

    /** TODO */
    using string_any_map = std::map<std::string, boost::any>;

    /** TODO */
    using string_view_any_map = std::map<std::string_view, boost::any>;

    /** TODO */
    inline constexpr struct any_empty_fn
    {
        template<typename Any>
        bool operator()(Any && a) const
        {
            if constexpr (program_options_2::tag_invocable<any_empty_fn, Any>) {
                return program_options_2::tag_invoke(*this, (Any &&) a);
            } else if constexpr (std::is_same_v<
                                     std::remove_cvref_t<Any>,
                                     boost::any>) {
                return a.empty();
            } else {
                return !a.has_value();
            }
        }
    } any_empty;

    /** TODO */
    template<typename T>
    struct any_cast_fn
    {
        template<typename Any>
        decltype(auto) operator()(Any && a) const
        {
            if constexpr (program_options_2::
                              tag_invocable<any_cast_fn, Any, type_<T>>) {
                return program_options_2::tag_invoke(
                    *this, (Any &&) a, type_c<T>);
            } else if constexpr (std::is_same_v<
                                     std::remove_cvref_t<Any>,
                                     boost::any>) {
                return boost::any_cast<T>(a);
            } else {
                return std::any_cast<T>(a);
            }
        }
    };

    /** TODO */
    template<typename T>
    inline constexpr any_cast_fn<T> any_cast;

    namespace detail {
        enum struct option_kind { positional, argument };

        enum struct required_t { yes, no };

        enum struct action_kind {
            assign,
            count,
            insert,
            help,
            version,
            response_file
        };

        template<
            option_kind Kind,
            typename T,
            typename Value = no_value,
            required_t Required = required_t::no,
            int Choices = 0,
            typename ChoiceType = T,
            typename Validator = no_value>
        struct option
        {
            using type = T;
            using value_type = Value;
            using choice_type = std::conditional_t<
                std::is_same_v<ChoiceType, void>,
                no_value,
                ChoiceType>;
            using validator_type = Validator;

            constexpr static bool positional = Kind == option_kind::positional;
            constexpr static bool required = Required == required_t::yes;
            constexpr static int num_choices = Choices;

            std::string_view names;
            std::string_view help_text;
            action_kind action;
            int args;
            value_type default_value;
            std::array<choice_type, num_choices> choices;
            std::string_view arg_display_name;
            mutable validator_type validator;
        };

        template<typename T>
        struct is_option : std::false_type
        {};
        template<
            option_kind Kind,
            typename T,
            typename Value,
            required_t Required,
            int Choices,
            typename ChoiceType,
            typename Validator>
        struct is_option<
            option<Kind, T, Value, Required, Choices, ChoiceType, Validator>>
            : std::true_type
        {};

        template<bool MutuallyExclusive, typename... Options>
        struct option_group
        {
            // name is only nonempty when this is a group gated by some verb,
            // e.g. git push arg arg.
            std::string_view name;
            hana::tuple<Options...> options;

            constexpr static bool mutually_exclusive = MutuallyExclusive;
        };

        template<typename T>
        struct is_group : std::false_type
        {};
        template<bool MutuallyExclusive, typename... Options>
        struct is_group<option_group<MutuallyExclusive, Options...>>
            : std::true_type
        {};

        inline bool positional(std::string_view name) { return name[0] != '-'; }
        inline bool short_(std::string_view name)
        {
            return name[0] == '-' && name[1] != '-';
        }
        inline bool long_(std::string_view name)
        {
            return name[0] == '-' && name[1] == '-';
        }

        inline bool leading_dash(std::string_view str)
        {
            return !str.empty() && str[0] == '-';
        }

        template<
            option_kind Kind,
            typename T,
            typename Value,
            required_t Required,
            int Choices,
            typename ChoiceType,
            typename Validator>
        bool positional(option<
                        Kind,
                        T,
                        Value,
                        Required,
                        Choices,
                        ChoiceType,
                        Validator> const & opt)
        {
            return detail::positional(opt.names);
        }

        template<typename Option>
        constexpr bool flag()
        {
            return std::is_same_v<
                Option,
                option<option_kind::argument, bool, bool, required_t::yes>>;
        }

        template<
            option_kind Kind,
            typename T,
            typename Value,
            required_t Required,
            int Choices,
            typename ChoiceType,
            typename Validator>
        bool optional_arg(option<
                          Kind,
                          T,
                          Value,
                          Required,
                          Choices,
                          ChoiceType,
                          Validator> const & opt)
        {
            return opt.args == zero_or_one || opt.args == zero_or_more;
        }

        template<
            option_kind Kind,
            typename T,
            typename Value,
            required_t Required,
            int Choices,
            typename ChoiceType,
            typename Validator>
        bool multi_arg(option<
                       Kind,
                       T,
                       Value,
                       Required,
                       Choices,
                       ChoiceType,
                       Validator> const & opt)
        {
            return opt.args == zero_or_more || opt.args == one_or_more;
        }
    }

    /** TODO */
    template<
        detail::option_kind Kind,
        typename T,
        typename Value,
        detail::required_t Required,
        int Choices,
        typename ChoiceType,
        typename Validator>
    std::string_view storage_name(detail::option<
                                  Kind,
                                  T,
                                  Value,
                                  Required,
                                  Choices,
                                  ChoiceType,
                                  Validator> const & opt);

}}

#endif

ext: hpp