db 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. <%!-lmysqlclient%><%@ class mypage %><%#
  2. #include <mysql/mysql.h>
  3. #include <json/json.h>
  4. #include <cpoll/threadpool.H>
  5. #include <list>
  6. #include "connectioninfo.H"
  7. #include "generic_pool.H"
  8. #include "world.H"
  9. using namespace CP;
  10. using namespace cppsp;
  11. using namespace std;
  12. class myStatement
  13. {
  14. public:
  15. MYSQL* db;
  16. int rn;
  17. int r;
  18. long unsigned int len1;
  19. MYSQL_STMT* stmt;
  20. MYSQL_BIND param[1], results[1];
  21. myStatement() {
  22. db=doConnect(NULL);
  23. stmt=mysql_stmt_init(db);
  24. const char* sql="SELECT randomNumber FROM World WHERE id = ?";
  25. mysql_stmt_prepare(stmt,sql,strlen(sql));
  26. memset(param, 0, sizeof(param));
  27. memset(results, 0, sizeof(results));
  28. param[0].buffer_type = MYSQL_TYPE_LONG;
  29. param[0].buffer = (char *)&rn;
  30. param[0].buffer_length = sizeof(rn);
  31. param[0].is_null = 0;
  32. param[0].length = NULL;
  33. results[0].buffer_type= MYSQL_TYPE_LONG;
  34. results[0].buffer = &r;
  35. results[0].buffer_length = sizeof(r);
  36. results[0].is_null = 0;
  37. results[0].length = &len1;
  38. if(mysql_stmt_bind_param(stmt,param)) throw runtime_error(mysql_stmt_error(stmt));
  39. if(mysql_stmt_bind_result(stmt, results)) throw runtime_error(mysql_stmt_error(stmt));
  40. }
  41. ~myStatement() {
  42. mysql_stmt_close(stmt);
  43. doDisconnect(NULL,db);
  44. }
  45. };
  46. myStatement* cStatement(void*) {
  47. return new myStatement();
  48. }
  49. void dStatement(void*, myStatement* s) {
  50. delete s;
  51. }
  52. genericPool<myStatement*,128> stmtPool(&cStatement,&dStatement);
  53. ThreadPool tp(32);
  54. int curOperations=0;
  55. static const int maxOperations=MYSQL_MAX_CONNECTIONS;
  56. list<EventFD*> waitingThreads;
  57. void do_init_thread(void*) {
  58. mysql_thread_init();
  59. }
  60. void do_deinit_thread(void*) {
  61. mysql_thread_end();
  62. }
  63. extern "C" void initModule() {
  64. mysql_library_init(0,NULL,NULL);
  65. tp.afterStart=&do_init_thread;
  66. tp.beforeExit=&do_deinit_thread;
  67. }
  68. %><%$
  69. EventFD efd{0,EFD_SEMAPHORE};
  70. int queries=1;
  71. world* items;
  72. myStatement* stmt;
  73. void tpFunc() {
  74. //mysql_thread_init();
  75. for (int i=0;i<queries;i++){
  76. items[i].id=stmt->rn=rand()%10000;
  77. if(mysql_stmt_execute(stmt->stmt)) throw runtime_error(mysql_stmt_error(stmt->stmt));
  78. if(mysql_stmt_fetch(stmt->stmt)==0) {
  79. items[i].rnd=stmt->r;
  80. } else {
  81. items[i].rnd=0;
  82. }
  83. }
  84. efd.sendEvent(1);
  85. }
  86. //asynchronously load the data in the doInit() function, and defer page rendering until data is available
  87. void doInit() override {
  88. if(unlikely(curOperations>=maxOperations)) {
  89. //too many threads. need to wait.
  90. waitingThreads.push_back(&efd);
  91. efd.getEvent({&mypage::waitCB,this});
  92. poll->add(efd);
  93. return;
  94. }
  95. curOperations++;
  96. auto it=request->queryString.find("queries");
  97. if(it!=request->queryString.end()) {
  98. queries=atoi((*it).second);
  99. }
  100. if(queries<1)queries=1;
  101. if(queries>500)queries=500;
  102. int i;
  103. items=(world*)sp->alloc(sizeof(world)*queries);
  104. stmt=stmtPool.get();
  105. poll->add(efd);
  106. tp.invoke({&mypage::tpFunc,this});
  107. efd.getEvent({&mypage::efdCB,this});
  108. }
  109. void efdCB(eventfd_t efdVal) {
  110. curOperations--;
  111. if(curOperations<maxOperations) {
  112. if(unlikely(!waitingThreads.empty())) {
  113. waitingThreads.front()->sendEvent(1);
  114. waitingThreads.pop_front();
  115. }
  116. }
  117. stmtPool.put(stmt);
  118. Page::doInit();
  119. }
  120. void waitCB(eventfd_t efdVal) {
  121. this->doInit();
  122. }
  123. %>[<%
  124. for (int i=0;i<queries;i++){
  125. if(i>0) output.write(',');
  126. %>{"id":<%=items[i].id%>,"randomNumber":<%=items[i].rnd%>}<%
  127. }
  128. response->headers["Content-Type"]="application/json";
  129. response->headers["Server"]="cppsp/0.2";
  130. %>]