fortune 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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. using namespace CP;
  9. using namespace cppsp;
  10. using namespace std;
  11. bool comp_string(const String& x, const String& y) {
  12. if (x.len == 0 || y.len == 0) return x.len < y.len;
  13. int complen = x.len < y.len ? x.len : y.len;
  14. int tmp = memcmp(x.d, y.d, complen);
  15. if (tmp == 0) return x.len < y.len;
  16. else return tmp < 0;
  17. }
  18. struct fortune
  19. {
  20. String message;
  21. int id;
  22. bool operator<(const fortune& other) const {
  23. return comp_string(message,other.message);
  24. }
  25. };
  26. genericPool<MYSQL*,64> sqlPool(&doConnect,&doDisconnect);
  27. ThreadPool tp(16);
  28. void do_init_thread(void*) {
  29. mysql_thread_init();
  30. }
  31. void do_deinit_thread(void*) {
  32. mysql_thread_end();
  33. }
  34. extern "C" void initModule() {
  35. mysql_library_init(0,NULL,NULL);
  36. tp.afterStart=&do_init_thread;
  37. tp.beforeExit=&do_deinit_thread;
  38. }
  39. %><%$
  40. EventFD efd{0,EFD_SEMAPHORE};
  41. vector<fortune> fortunes;
  42. MYSQL* db;
  43. //function to be executed in the thread pool
  44. void tpFunc() {
  45. mysql_query(db, "SELECT id, message FROM Fortune;");
  46. MYSQL_RES *sqlres = mysql_store_result(db);
  47. if (sqlres==NULL) throw runtime_error(mysql_error(db));
  48. MYSQL_ROW row;
  49. while( (row=mysql_fetch_row(sqlres)) ){
  50. fortunes.push_back({sp->addString(row[1]),atoi(row[0])});
  51. }
  52. mysql_free_result(sqlres);
  53. fortunes.push_back({"Additional fortune added at request time.",0});
  54. sort(fortunes.begin(),fortunes.end());
  55. efd.sendEvent(1);
  56. }
  57. //asynchronously load the data in the doInit() function, and defer page rendering until data is available
  58. void doInit() override {
  59. response->headers["Server"]="cppsp/0.2";
  60. db=sqlPool.get();
  61. poll->add(efd);
  62. tp.invoke({&mypage::tpFunc,this});
  63. efd.getEvent({&mypage::efdCB,this});
  64. }
  65. void efdCB(eventfd_t efdVal) {
  66. sqlPool.put(db);
  67. Page::doInit();
  68. }
  69. %>
  70. <!DOCTYPE html>
  71. <html>
  72. <head><title>Fortunes</title></head>
  73. <body>
  74. <table>
  75. <tr><th>id</th><th>message</th></tr>
  76. <%
  77. for(int i=0;i<fortunes.size();i++) {
  78. %>
  79. <tr><td><%=fortunes[i].id%></td><td><%htmlEscape(fortunes[i].message,output);%></td></tr><%
  80. }
  81. %>
  82. </table>
  83. </body>
  84. </html>