settings.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License, version 2.0, as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is also distributed with certain software (including
  9. * but not limited to OpenSSL) that is licensed under separate terms,
  10. * as designated in a particular file or component or in included license
  11. * documentation. The authors of MySQL hereby grant you an
  12. * additional permission to link the program and your derivative works
  13. * with the separately licensed software that they have included with
  14. * MySQL.
  15. *
  16. * Without limiting anything contained in the foregoing, this file,
  17. * which is part of MySQL Connector/C++, is also subject to the
  18. * Universal FOSS Exception, version 1.0, a copy of which can be found at
  19. * http://oss.oracle.com/licenses/universal-foss-exception.
  20. *
  21. * This program is distributed in the hope that it will be useful, but
  22. * WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  24. * See the GNU General Public License, version 2.0, for more details.
  25. *
  26. * You should have received a copy of the GNU General Public License
  27. * along with this program; if not, write to the Free Software Foundation, Inc.,
  28. * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  29. */
  30. #ifndef MYSQLX_DETAIL_SETTINGS_H
  31. #define MYSQLX_DETAIL_SETTINGS_H
  32. #include "../common.h"
  33. #include "../document.h"
  34. #include <chrono>
  35. #include <list>
  36. #include <chrono>
  37. namespace mysqlx {
  38. namespace internal {
  39. /*
  40. Note: Options and SSLMode enumerations are given by Traits template parameter
  41. to allow defining (and documenting) them in the main settings.h header.
  42. */
  43. template <typename Traits>
  44. class Settings_detail
  45. : public common::Settings_impl
  46. {
  47. using Value = common::Value;
  48. using SOption = typename Traits::Options;
  49. using COption = typename Traits::CliOptions;
  50. using SSLMode = typename Traits::SSLMode;
  51. using AuthMethod = typename Traits::AuthMethod;
  52. public:
  53. template <bool session_only,typename OPT,typename... Ty>
  54. void set(OPT opt, Ty&&... rest)
  55. {
  56. do_set(get_options<session_only>(opt, std::forward<Ty>(rest)...));
  57. }
  58. protected:
  59. /*
  60. Declare options that require specific type of value (mostly enumerations).
  61. For such options we do not accept setting them to arbitrary values. Instead
  62. an overload of opt_val() with appropriate type will be used to set value
  63. of the option.
  64. */
  65. #define OPT_VAL_TYPE(X) \
  66. X(SSL_MODE,SSLMode) \
  67. X(AUTH,AuthMethod)
  68. #define CHECK_OPT(Opt,Type) \
  69. if (opt == Option_impl::Opt) \
  70. throw Error(#Opt "setting requires value of type " #Type);
  71. /*
  72. Store option value in Value object (with basic run-time type checks)
  73. TODO: More precise type checking using per-option types.
  74. */
  75. static Value opt_val(Option_impl opt, Value &&val)
  76. {
  77. OPT_VAL_TYPE(CHECK_OPT)
  78. return val;
  79. }
  80. /*
  81. For types which are not convertible to Value, but can be converted to string
  82. go through string conversion.
  83. */
  84. template <
  85. typename V,
  86. typename std::enable_if<std::is_convertible<V,string>::value>::type*
  87. = nullptr
  88. >
  89. static Value opt_val(Option_impl opt, V &&val)
  90. {
  91. OPT_VAL_TYPE(CHECK_OPT)
  92. return string(val);
  93. }
  94. template<typename _Rep, typename _Period>
  95. static Value opt_val(Option_impl opt,
  96. const std::chrono::duration<_Rep, _Period> &val)
  97. {
  98. if (opt != Option_impl::CONNECT_TIMEOUT)
  99. {
  100. std::stringstream err_msg;
  101. err_msg << "Option " << option_name(opt) << " does not accept time value";
  102. throw_error(err_msg.str().c_str());
  103. }
  104. return Value(std::chrono::duration_cast<std::chrono::milliseconds>(val)
  105. .count());
  106. }
  107. static Value opt_val(Option_impl opt, SSLMode m)
  108. {
  109. if (opt != Option_impl::SSL_MODE)
  110. throw Error(
  111. "SessionSettings::SSLMode value can only be used on SSL_MODE setting."
  112. );
  113. return unsigned(m);
  114. }
  115. static Value opt_val(Option_impl opt, AuthMethod m)
  116. {
  117. if (opt != Option_impl::AUTH)
  118. throw Error(
  119. "SessionSettings::AuthMethod value can only be used on AUTH setting."
  120. );
  121. return unsigned(m);
  122. }
  123. template<typename _Rep, typename _Period>
  124. static Value opt_val(Client_option_impl opt,
  125. const std::chrono::duration<_Rep,_Period> &duration)
  126. {
  127. if (opt != Client_option_impl::POOL_QUEUE_TIMEOUT &&
  128. opt != Client_option_impl::POOL_MAX_IDLE_TIME)
  129. {
  130. std::stringstream err_msg;
  131. err_msg << "Option " << option_name(opt) << " does not accept time value";
  132. throw_error(err_msg.str().c_str());
  133. }
  134. return Value(std::chrono::duration_cast<std::chrono::milliseconds>(duration)
  135. .count());
  136. }
  137. template <
  138. typename V,
  139. typename std::enable_if<std::is_convertible<V,int>::value>::type*
  140. = nullptr
  141. >
  142. static Value opt_val(Client_option_impl, V &&val)
  143. {
  144. //ClientOptions are all bool or int, so convertible to int
  145. return val;
  146. }
  147. using session_opt_val_t = std::pair<int, Value>;
  148. using session_opt_list_t = std::list<session_opt_val_t>;
  149. /*
  150. Set list of options with consistency checks.
  151. This operation is atomic - settings are changed only if all options could
  152. be set without error, otherwise settings remain unchanged.
  153. */
  154. void do_set(session_opt_list_t&&);
  155. /*
  156. ClientOptions and Options are converted to int, one positive and other
  157. negative
  158. */
  159. static
  160. int option_to_int(Option_impl opt)
  161. {
  162. return static_cast<int>(opt);
  163. }
  164. static
  165. int option_to_int(Client_option_impl opt)
  166. {
  167. return -static_cast<int>(opt);
  168. }
  169. static
  170. Option_impl int_to_option(int opt)
  171. {
  172. return static_cast<Option_impl>(opt);
  173. }
  174. static
  175. Client_option_impl int_to_client_option(int opt)
  176. {
  177. return static_cast<Client_option_impl>(-opt);
  178. }
  179. /*
  180. Templates that collect varargs list of options into opt_list_t list
  181. that can be passed to do_set().
  182. */
  183. template<bool session_only>
  184. static session_opt_list_t get_options()
  185. {
  186. return {};
  187. }
  188. /*
  189. Note: if we ever support options without values, another overload is
  190. needed: get_options(Option opt, Option opt1, R&... rest).
  191. */
  192. template <bool session_only,typename V, typename... Ty>
  193. static session_opt_list_t get_options(SOption opt, V&& val, Ty&&... rest)
  194. {
  195. Option_impl oo = (Option_impl)(unsigned)opt;
  196. session_opt_list_t opts = get_options<session_only>(std::forward<Ty>(rest)...);
  197. opts.emplace_front(
  198. option_to_int(oo),
  199. Settings_detail::opt_val(oo, std::forward<V>(val))
  200. );
  201. return opts;
  202. }
  203. template <bool session_only,typename V, typename... Ty,
  204. typename std::enable_if<!session_only,int>::type*
  205. = nullptr>
  206. static session_opt_list_t get_options(COption opt, V&& val, Ty&&... rest)
  207. {
  208. Client_option_impl oo = (Client_option_impl)(unsigned)opt;
  209. session_opt_list_t opts = get_options<session_only>(std::forward<Ty>(rest)...);
  210. opts.emplace_front(
  211. option_to_int(oo),
  212. Settings_detail::opt_val(oo, std::forward<V>(val))
  213. );
  214. return opts;
  215. }
  216. /*
  217. Note: Methods below rely on the fact that DevAPI SessionOption constants
  218. have the same numeric values as common::Settings_impl::Option ones.
  219. */
  220. void erase(SOption opt)
  221. {
  222. Settings_impl::erase((Option_impl)(unsigned)opt);
  223. }
  224. void erase(COption opt)
  225. {
  226. Settings_impl::erase((Client_option_impl)(unsigned)opt);
  227. }
  228. bool has_option(SOption opt)
  229. {
  230. return Settings_impl::has_option((Option_impl)(unsigned)opt);
  231. }
  232. bool has_option(COption opt)
  233. {
  234. return Settings_impl::has_option((Client_option_impl)(unsigned)opt);
  235. }
  236. Value get(SOption opt)
  237. {
  238. return Settings_impl::get((Option_impl)(unsigned)opt);
  239. }
  240. Value get(COption opt)
  241. {
  242. return Settings_impl::get((Client_option_impl)(unsigned)opt);
  243. }
  244. };
  245. } // internal namespace
  246. } // mysqlx namespace
  247. #endif