PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/hphp/runtime/ext/async_mysql/ext_async_mysql.h

https://github.com/soitun/hiphop-php
C Header | 451 lines | 287 code | 101 blank | 63 comment | 2 complexity | af6986b2ae76ca2d2e6fba81eabf322e MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. */
  16. #pragma once
  17. #include <algorithm>
  18. #include <memory>
  19. #include <squangle/mysql_client/AsyncMysqlClient.h>
  20. #include <squangle/mysql_client/AsyncConnectionPool.h>
  21. #include <squangle/mysql_client/SSLOptionsProviderBase.h>
  22. #include <squangle/mysql_client/Row.h>
  23. #include <squangle/logger/DBEventCounter.h>
  24. #include "hphp/runtime/ext/asio/asio-external-thread-event.h"
  25. #include "hphp/runtime/ext/extension.h"
  26. #include <folly/Format.h>
  27. namespace HPHP {
  28. ///////////////////////////////////////////////////////////////////////////////
  29. struct c_Vector;
  30. namespace am = facebook::common::mysql_client;
  31. namespace db = facebook::db;
  32. ///////////////////////////////////////////////////////////////////////////////
  33. // class AsyncMysqlConnectionPool
  34. struct AsyncMysqlConnectionPool {
  35. AsyncMysqlConnectionPool() = default;
  36. void sweep();
  37. std::shared_ptr<am::AsyncConnectionPool> m_async_pool;
  38. static const StaticString s_className;
  39. AsyncMysqlConnectionPool(const AsyncMysqlConnectionPool&) = delete;
  40. AsyncMysqlConnectionPool& operator=(const AsyncMysqlConnectionPool&) = delete;
  41. };
  42. ///////////////////////////////////////////////////////////////////////////////
  43. // class AsyncMysqlConnection
  44. struct AsyncMysqlConnection {
  45. AsyncMysqlConnection();
  46. AsyncMysqlConnection(const AsyncMysqlConnection&) = delete;
  47. AsyncMysqlConnection& operator=(const AsyncMysqlConnection&) = delete;
  48. void sweep();
  49. void setConnection(std::unique_ptr<am::Connection> conn);
  50. void setConnectOperation(std::shared_ptr<am::ConnectOperation> op);
  51. void setClientStats(db::ClientPerfStats perfStats);
  52. void verifyValidConnection();
  53. bool isValidConnection();
  54. static Class* getClass();
  55. static Object newInstance(
  56. std::unique_ptr<am::Connection> conn,
  57. std::shared_ptr<am::ConnectOperation> conn_op = nullptr,
  58. db::ClientPerfStats clientStats = db::ClientPerfStats());
  59. using AttributeMap = std::unordered_map<std::string, std::string>;
  60. Object query(
  61. ObjectData* this_,
  62. am::Query query,
  63. int64_t timeout_micros = -1,
  64. const AttributeMap& queryAttributes = AttributeMap());
  65. std::unique_ptr<am::Connection> m_conn;
  66. String m_host;
  67. int m_port;
  68. bool m_closed;
  69. // Stats at the moment the Connection was created
  70. // Only available if the connection was created inside the AsyncMysqlClient.
  71. db::ClientPerfStats m_clientStats;
  72. std::shared_ptr<am::ConnectOperation> m_op;
  73. static Class* s_class;
  74. static const StaticString s_className;
  75. };
  76. ///////////////////////////////////////////////////////////////////////////////
  77. // class MySSLContext
  78. struct MySSLContextProvider {
  79. MySSLContextProvider() {}
  80. explicit MySSLContextProvider(
  81. std::shared_ptr<am::SSLOptionsProviderBase> provider);
  82. MySSLContextProvider& operator=(const MySSLContextProvider& that_) = delete;
  83. static Object newInstance(
  84. std::shared_ptr<am::SSLOptionsProviderBase> ssl_provider);
  85. static Class* getClass();
  86. std::shared_ptr<am::SSLOptionsProviderBase> getSSLProvider();
  87. void setSSLProvider(std::shared_ptr<am::SSLOptionsProviderBase> ssl_provider);
  88. static Class* s_class;
  89. static const StaticString s_className;
  90. std::shared_ptr<am::SSLOptionsProviderBase> m_provider;
  91. };
  92. ///////////////////////////////////////////////////////////////////////////////
  93. // class AsyncMysqlConnectionOptions
  94. struct AsyncMysqlConnectionOptions {
  95. AsyncMysqlConnectionOptions();
  96. static Class* getClass();
  97. const am::ConnectionOptions& getConnectionOptions();
  98. static Class* s_class;
  99. static const StaticString s_className;
  100. am::ConnectionOptions m_conn_opts;
  101. TYPE_SCAN_IGNORE_FIELD(m_conn_opts);
  102. };
  103. ///////////////////////////////////////////////////////////////////////////////
  104. // class AsyncMysqlResult
  105. struct AsyncMysqlResult {
  106. virtual ~AsyncMysqlResult() {}
  107. int64_t elapsedMicros();
  108. double startTime();
  109. double endTime();
  110. Object clientStats();
  111. void create(std::shared_ptr<am::Operation> op, db::ClientPerfStats values) {
  112. m_op = std::move(op);
  113. m_clientStats = std::move(values);
  114. }
  115. am::Operation* op();
  116. void sweep() { m_op.reset(); }
  117. bool sslSessionReused();
  118. String getSslCertCn();
  119. String getSslCertSan();
  120. String getSslCertExtensions();
  121. bool isSslCertValidationEnforced();
  122. std::shared_ptr<am::Operation> m_op;
  123. db::ClientPerfStats m_clientStats;
  124. };
  125. // Intended to just hold extra data about the Operation. This should be created
  126. // in `AsyncMysqlConnection`.
  127. struct AsyncMysqlConnectResult : AsyncMysqlResult {
  128. AsyncMysqlConnectResult() = default;
  129. ~AsyncMysqlConnectResult() override {}
  130. static Class* getClass();
  131. static Object newInstance(std::shared_ptr<am::Operation> op,
  132. db::ClientPerfStats clientStats);
  133. static Class* s_class;
  134. static const StaticString s_className;
  135. AsyncMysqlConnectResult(const AsyncMysqlConnectResult&) = delete;
  136. AsyncMysqlConnectResult& operator=(const AsyncMysqlConnectResult&) = delete;
  137. };
  138. ///////////////////////////////////////////////////////////////////////////////
  139. // class AsyncMysqlErrorResult
  140. struct AsyncMysqlErrorResult : AsyncMysqlResult {
  141. AsyncMysqlErrorResult() = default;
  142. ~AsyncMysqlErrorResult() override {}
  143. static Class* getClass();
  144. static Object newInstance(std::shared_ptr<am::Operation> op,
  145. db::ClientPerfStats clientStats);
  146. static Class* s_class;
  147. static const StaticString s_className;
  148. AsyncMysqlErrorResult(const AsyncMysqlErrorResult&) = delete;
  149. AsyncMysqlErrorResult& operator=(const AsyncMysqlErrorResult&) = delete;
  150. };
  151. ///////////////////////////////////////////////////////////////////////////////
  152. // class AsyncMysqlQueryErrorResult
  153. struct AsyncMysqlQueryErrorResult {
  154. AsyncMysqlQueryErrorResult();
  155. AsyncMysqlQueryErrorResult(const AsyncMysqlQueryErrorResult&) = delete;
  156. AsyncMysqlQueryErrorResult& operator=(const AsyncMysqlQueryErrorResult&) =
  157. delete;
  158. void sweep();
  159. void create(std::shared_ptr<am::Operation> op,
  160. db::ClientPerfStats values,
  161. req::ptr<c_Vector> results);
  162. static Class* getClass();
  163. static Object newInstance(std::shared_ptr<am::Operation> op,
  164. db::ClientPerfStats values,
  165. req::ptr<c_Vector> results);
  166. req::ptr<c_Vector> m_query_results;
  167. static Class* s_class;
  168. static const StaticString s_className;
  169. // extends AsyncMysqlErrorResult
  170. //
  171. // The address of native data is computed using the size of the native data
  172. // as an offset from the object data. To ensure that the offset to the parent
  173. // class remains the same, we simulate inheritance by placing the parent
  174. // class below the object instead of using c++ inheritance.
  175. AsyncMysqlErrorResult m_parent;
  176. };
  177. ///////////////////////////////////////////////////////////////////////////////
  178. // This class is shared across the QueryResult and RowBlocks for faster
  179. // indexing of row columns.
  180. // By using HPHP::String instead of other string types, we are able
  181. // to build maps where we just reuse them so we avoid copying.
  182. // Thus, eliminating repetition of map keys and also gain speed.
  183. struct FieldIndex {
  184. explicit FieldIndex(const am::RowFields* row_fields);
  185. size_t getFieldIndex(String field_name) const;
  186. String getFieldString(size_t field_index) const;
  187. private:
  188. // NB: It's possible to just use a req::vector_map<String> for names,
  189. // and rely on insertion order to compute indexes, but sometimes this
  190. // FieldIndex has duplicate names. last-name-wins, requiring the map.
  191. req::vector<String> field_names_;
  192. req::fast_map<String, size_t, hphp_string_hash, hphp_string_same>
  193. field_name_map_;
  194. };
  195. ///////////////////////////////////////////////////////////////////////////////
  196. // class AsyncMysqlQueryResult
  197. struct AsyncMysqlQueryResult : AsyncMysqlResult {
  198. AsyncMysqlQueryResult() = default;
  199. ~AsyncMysqlQueryResult() override {}
  200. void sweep();
  201. void
  202. create(std::shared_ptr<am::Operation> op, db::ClientPerfStats values,
  203. am::QueryResult query_result, bool noIndexUsed);
  204. Object buildRows(bool as_maps, bool typed_values);
  205. Array buildTypedVecMaps();
  206. static Class* getClass();
  207. static Object
  208. newInstance(std::shared_ptr<am::Operation> op, db::ClientPerfStats values,
  209. am::QueryResult query_result, bool noIndexUsed);
  210. std::unique_ptr<am::QueryResult> m_query_result;
  211. bool m_no_index_used;
  212. // Created here for buildRows and passed to RowBlocks
  213. req::shared_ptr<FieldIndex> m_field_index;
  214. static Class* s_class;
  215. static const StaticString s_className;
  216. AsyncMysqlQueryResult(const AsyncMysqlQueryResult&) = delete;
  217. AsyncMysqlQueryResult& operator=(const AsyncMysqlQueryResult&) = delete;
  218. };
  219. ///////////////////////////////////////////////////////////////////////////////
  220. // Async events
  221. struct AsyncMysqlConnectEvent final : AsioExternalThreadEvent {
  222. explicit AsyncMysqlConnectEvent(std::shared_ptr<am::ConnectOperation> op) {
  223. m_op = op;
  224. }
  225. void opFinished() { markAsFinished(); }
  226. void setClientStats(db::ClientPerfStats stats) {
  227. m_clientStats = std::move(stats);
  228. }
  229. protected:
  230. void unserialize(TypedValue& result) final;
  231. private:
  232. std::shared_ptr<am::ConnectOperation> m_op;
  233. db::ClientPerfStats m_clientStats;
  234. };
  235. struct AsyncMysqlQueryEvent final : AsioExternalThreadEvent {
  236. AsyncMysqlQueryEvent(ObjectData* conn,
  237. std::shared_ptr<am::QueryOperation> op)
  238. : AsioExternalThreadEvent(conn) {
  239. m_query_op = std::move(op);
  240. }
  241. void opFinished() { markAsFinished(); }
  242. void setClientStats(db::ClientPerfStats stats) {
  243. m_clientStats = std::move(stats);
  244. }
  245. protected:
  246. void unserialize(TypedValue& result) final;
  247. private:
  248. std::shared_ptr<am::QueryOperation> m_query_op;
  249. db::ClientPerfStats m_clientStats;
  250. };
  251. struct AsyncMysqlMultiQueryEvent final : AsioExternalThreadEvent {
  252. AsyncMysqlMultiQueryEvent(ObjectData* conn,
  253. std::shared_ptr<am::MultiQueryOperation> op)
  254. : AsioExternalThreadEvent(conn) {
  255. m_multi_op = op;
  256. }
  257. void opFinished() { markAsFinished(); }
  258. void setClientStats(db::ClientPerfStats stats) {
  259. m_clientStats = std::move(stats);
  260. }
  261. protected:
  262. void unserialize(TypedValue& result) final;
  263. private:
  264. std::shared_ptr<am::MultiQueryOperation> m_multi_op;
  265. db::ClientPerfStats m_clientStats;
  266. };
  267. struct AsyncMysqlConnectAndMultiQueryEvent final : AsioExternalThreadEvent {
  268. explicit AsyncMysqlConnectAndMultiQueryEvent(
  269. std::shared_ptr<am::ConnectOperation> op) {
  270. m_connect_op = op;
  271. if (m_connect_op->getCertValidationCallback() &&
  272. m_connect_op->getConnectionContext() == nullptr) {
  273. auto context = std::make_unique<db::ConnectionContextBase>();
  274. m_connect_op->setConnectionContext(std::move(context));
  275. }
  276. }
  277. void setQueryOp(std::shared_ptr<am::MultiQueryOperation> op) {
  278. m_multi_query_op = std::move(op);
  279. }
  280. void opFinished() { markAsFinished(); }
  281. void setClientStats(db::ClientPerfStats stats) {
  282. m_clientStats = std::move(stats);
  283. }
  284. protected:
  285. void unserialize(TypedValue& result) final;
  286. private:
  287. std::shared_ptr<am::ConnectOperation> m_connect_op;
  288. std::shared_ptr<am::MultiQueryOperation> m_multi_query_op;
  289. db::ClientPerfStats m_clientStats;
  290. };
  291. ///////////////////////////////////////////////////////////////////////////////
  292. // class AsyncMysqlRowBlock
  293. struct AsyncMysqlRowBlock {
  294. AsyncMysqlRowBlock() = default;
  295. void sweep();
  296. size_t getIndexFromVariant(const Variant& field);
  297. template <typename FieldType>
  298. FieldType getFieldAs(int64_t row, const Variant& field);
  299. static Class* getClass();
  300. static Object newInstance(am::RowBlock* row_block,
  301. req::shared_ptr<FieldIndex> indexer);
  302. std::unique_ptr<am::RowBlock> m_row_block;
  303. req::shared_ptr<FieldIndex> m_field_index;
  304. static Class* s_class;
  305. static const StaticString s_className;
  306. AsyncMysqlRowBlock(const AsyncMysqlRowBlock&) = delete;
  307. AsyncMysqlRowBlock& operator=(const AsyncMysqlRowBlock&) = delete;
  308. };
  309. ///////////////////////////////////////////////////////////////////////////////
  310. // class AsyncMysqlRowBlockIterator
  311. struct AsyncMysqlRowBlockIterator {
  312. AsyncMysqlRowBlockIterator() = default;
  313. static Class* getClass();
  314. static Object newInstance(Object row_block, size_t row_number);
  315. Object m_row_block;
  316. size_t m_row_number;
  317. static Class* s_class;
  318. static const StaticString s_className;
  319. AsyncMysqlRowBlockIterator(const AsyncMysqlRowBlockIterator&) = delete;
  320. AsyncMysqlRowBlockIterator& operator=(const AsyncMysqlRowBlockIterator&) =
  321. delete;
  322. };
  323. ///////////////////////////////////////////////////////////////////////////////
  324. // class AsyncMysqlRow
  325. struct AsyncMysqlRow {
  326. AsyncMysqlRow() = default;
  327. static Class* getClass();
  328. static Object newInstance(Object row_block, size_t row_number);
  329. Object m_row_block;
  330. size_t m_row_number;
  331. static Class* s_class;
  332. static const StaticString s_className;
  333. AsyncMysqlRow(const AsyncMysqlRow&) = delete;
  334. AsyncMysqlRow& operator=(const AsyncMysqlRow&) = delete;
  335. };
  336. ///////////////////////////////////////////////////////////////////////////////
  337. // class AsyncMysqlRowIterator
  338. struct AsyncMysqlRowIterator {
  339. AsyncMysqlRowIterator() = default;
  340. static Class* getClass();
  341. static Object newInstance(Object row, size_t field_number);
  342. Object m_row;
  343. size_t m_field_number;
  344. static Class* s_class;
  345. static const StaticString s_className;
  346. AsyncMysqlRowIterator(const AsyncMysqlRowIterator&) = delete;
  347. AsyncMysqlRowIterator& operator=(const AsyncMysqlRowIterator&) = delete;
  348. };
  349. ///////////////////////////////////////////////////////////////////////////////
  350. }