Hi all,

I have added static assertion for validating retry control parameters,
so that user will get complier error if giving invalid inputs. Below is the
diff.

diff --git a/src/base/try_again_decorator.h b/src/base/try_again_decorator.h
index e676697..b11194d 100644
--- a/src/base/try_again_decorator.h
+++ b/src/base/try_again_decorator.h
@@ -98,6 +98,8 @@ class TryAgainDecorator {
  public:
   template<class T, class... Args>
   static Decorator<T(Args...)> DecorateFunction(T (*f)(Args ...)) {
+    static_assert((timeout_ms / interval_ms) > 1,
+                  "timeout must be larger than interval!");
     RetryControl ctrl({0, interval_ms * 1000 * 1000}, timeout_ms);
     return Decorator<T(Args...)>
         (std::function<T(Args...)>(f), ctrl);

Regards, Vu

> -----Original Message-----
> From: Vu Minh Nguyen [mailto:vu.m.ngu...@dektech.com.au]
> Sent: Tuesday, November 28, 2017 2:13 PM
> To: anders.wid...@ericsson.com; hans.nordeb...@ericsson.com
> Cc: opensaf-devel@lists.sourceforge.net; Vu Minh Nguyen
> <vu.m.ngu...@dektech.com.au>
> Subject: [PATCH 1/1] base: create generic try-again handling decorator for
AIS
> APIs [#2702]
> 
> Make generic C++ decorator for handling SA_AIS_ERR_TRY_AGAIN return
> code
> of AIS APIs.
> ---
>  src/base/Makefile.am                       |   5 +-
>  src/base/tests/try_again_decorator_test.cc |  48 +++++++++++++
>  src/base/try_again_decorator.h             | 109
> +++++++++++++++++++++++++++++
>  3 files changed, 161 insertions(+), 1 deletion(-)
>  create mode 100644 src/base/tests/try_again_decorator_test.cc
>  create mode 100644 src/base/try_again_decorator.h
> 
> diff --git a/src/base/Makefile.am b/src/base/Makefile.am
> index 956cce6..f11b738 100644
> --- a/src/base/Makefile.am
> +++ b/src/base/Makefile.am
> @@ -150,6 +150,7 @@ noinst_HEADERS += \
>       src/base/unix_client_socket.h \
>       src/base/unix_server_socket.h \
>       src/base/unix_socket.h \
> +     src/base/try_again_decorator.h \
>       src/base/usrbuf.h
> 
>  TESTS += bin/testleap bin/libbase_test bin/core_common_test
> @@ -208,7 +209,9 @@ bin_libbase_test_SOURCES = \
>       src/base/tests/time_compare_test.cc \
>       src/base/tests/time_convert_test.cc \
>       src/base/tests/time_subtract_test.cc \
> -     src/base/tests/unix_socket_test.cc
> +     src/base/tests/unix_socket_test.cc \
> +     src/base/tests/try_again_decorator_test.cc
> +
> 
>  bin_libbase_test_LDADD = \
>       $(GTEST_DIR)/lib/libgtest.la \
> diff --git a/src/base/tests/try_again_decorator_test.cc
> b/src/base/tests/try_again_decorator_test.cc
> new file mode 100644
> index 0000000..ac8595d
> --- /dev/null
> +++ b/src/base/tests/try_again_decorator_test.cc
> @@ -0,0 +1,48 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2017 The OpenSAF Foundation
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are
> licensed
> + * under the GNU Lesser General Public License Version 2.1, February
1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#include "base/try_again_decorator.h"
> +#include "gtest/gtest.h"
> +
> +static unsigned counter = 0;
> +
> +SaAisErrorT TestMethod() {
> +  ++counter;
> +  return SA_AIS_ERR_TRY_AGAIN;
> +}
> +
> +TEST(TryAgainDecorator, DefaultRetryControl) {
> +  // default interval = 40ms, timeout = 10 * 1000ms
> +  using DefaultDecorator = base::TryAgainDecorator<>;
> +  auto DecorTestMethod = DefaultDecorator::DecorateFunction(TestMethod);
> +
> +  DecorTestMethod();
> +  EXPECT_GE(counter, 200);
> +  EXPECT_LE(counter, 250);
> +  counter = 0;
> +}
> +
> +TEST(TryAgainDecorator, GivenRetryControl) {
> +  // interval = 10ms, timeout = 1000ms
> +  using TryAgainDecorator = base::TryAgainDecorator<10, 1 * 1000>;
> +  auto DecorTestMethod  =
> TryAgainDecorator::DecorateFunction(TestMethod);
> +
> +  DecorTestMethod();
> +  EXPECT_GE(counter, 50);
> +  EXPECT_LE(counter, 100);
> +  counter = 0;
> +}
> diff --git a/src/base/try_again_decorator.h
b/src/base/try_again_decorator.h
> new file mode 100644
> index 0000000..e676697
> --- /dev/null
> +++ b/src/base/try_again_decorator.h
> @@ -0,0 +1,109 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * Copyright Ericsson AB 2017 - All Rights Reserved.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are
> licensed
> + * under the GNU Lesser General Public License Version 2.1, February
1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + */
> +
> +#ifndef BASE_TRY_AGAIN_DECORATOR_H_
> +#define BASE_TRY_AGAIN_DECORATOR_H_
> +
> +#include <iostream>
> +#include <functional>
> +#include <saAis.h>
> +#include "base/time.h"
> +
> +namespace base {
> +
> +//>
> +// C++ decorator which escapsulates try again handling.
> +//
> +// E.g:
> +// 1) If user wants to call saClmInitialize() which has try again
> +// handling inside using this decorator, do this:
> +//
> +// using TryAgainDecorator = base::TryAgainDecorator<>;
> +// auto saClmInitialize = TryAgainDecorator(::saClmInitialize);
> +// if (saClmInitialize(handle, cbs, version) != SA_AIS_OK) {
> +//    // error handling
> +// }
> +//
> +// 2) If user wants other retry control than default ones,
> +// such as interval = 10ms, timeout = 10second, do this:
> +//
> +// using TryAgainDecorator = base::TryAgainDecorator<
> +//                                  {0, 10 * 1000 * 1000},
> +//                                  10 * 1000
> +//                                  >
> +// auto saClmInitialize = TryAgainDecorator(::saClmInitialize);
> +// if (saClmInitialize(handle, cbs, version) != SA_AIS_OK) {
> +//    // error handling
> +// }
> +//
> +//<
> +
> +// Default sleep time b/w retries {second, ns}
> +static const timespec kInterval = {0, 40 * 1000 * 1000};
> +// Default maximum time for retry loop (ms)
> +static const uint64_t kTimeout  = 10 * 1000;
> +
> +struct RetryControl {
> +  RetryControl() : interval(kInterval), timeout(kTimeout) {}
> +  RetryControl(timespec i, uint64_t t) : interval(i), timeout(t) {}
> +  RetryControl(const RetryControl& ctrl)
> +      : interval(ctrl.interval), timeout(ctrl.timeout) {}
> +
> +  // Sleep time b/w retries
> +  timespec interval;
> +  // Maximum time for retry loop
> +  uint64_t timeout;
> +};
> +
> +template <class> class Decorator;
> +template <class T, class... Args>
> +class Decorator<T(Args ...)> {
> + public:
> +  explicit Decorator(const std::function<T(Args ...)>& f,
> +                     const RetryControl& ctrl)
> +      : f_{f}, retry_ctrl_{ctrl} {}
> +
> +  explicit Decorator(const std::function<T(Args ...)>& f) : f_{f} {}
> +
> +  T operator()(Args ... args) {
> +    T ais_error;
> +    base::Timer wtime(retry_ctrl_.timeout);
> +    while (wtime.is_timeout() == false) {
> +      ais_error = f_(args...);
> +      if (ais_error != SA_AIS_ERR_TRY_AGAIN) break;
> +      base::Sleep(retry_ctrl_.interval);
> +    }
> +    return ais_error;
> +  }
> +
> + private:
> +  const std::function<T(Args ...)> f_;
> +  RetryControl retry_ctrl_;
> +};
> +
> +template <uint64_t interval_ms = 40, uint64_t timeout_ms = 10 * 1000>
> +class TryAgainDecorator {
> + public:
> +  template<class T, class... Args>
> +  static Decorator<T(Args...)> DecorateFunction(T (*f)(Args ...)) {
> +    RetryControl ctrl({0, interval_ms * 1000 * 1000}, timeout_ms);
> +    return Decorator<T(Args...)>
> +        (std::function<T(Args...)>(f), ctrl);
> +  }
> +};
> +
> +}  // namespace base
> +
> +#endif  //< BASE_TRY_AGAIN_DECORATOR_H_
> --
> 1.9.1



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to