worker.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. extern "C" {
  2. #include <event2/bufferevent.h>
  3. #include <event2/buffer.h>
  4. #include <event2/event.h>
  5. }
  6. #include <vector>
  7. #include <pthread.h>
  8. #include <stdio.h>
  9. #include "evutils.h"
  10. #include "subproblem.h"
  11. typedef enum {
  12. WRKCCSTATE_AWAITCMD,
  13. WRKCCSTATE_RDPROBLEM,
  14. WRKCCSTATE_RDDPNODES,
  15. WRKCCSTATE_END
  16. } WrkCCState;
  17. struct WrkControllerConnInfo {
  18. WrkCCState state;
  19. unsigned short num_dpnodes;
  20. WrkControllerConnInfo() : state(WRKCCSTATE_AWAITCMD), num_dpnodes(0) {}
  21. };
  22. typedef enum { WT_NOT_RUNNING, WT_RUNNING, WT_SHOULD_STOP} WTState;
  23. static struct WrkControllerState {
  24. Subproblem *current_problem;
  25. unsigned short num_expected_dpnodes;
  26. vector<struct bufferevent *> dpnodes;
  27. unsigned short num_connected_dpnodes;
  28. WTState worker_thread_state;
  29. pthread_t worker_thread;
  30. WrkControllerState(): current_problem(NULL),
  31. worker_thread_state(WT_NOT_RUNNING) {}
  32. } wrkctrlstate;
  33. static void stop_working(void)
  34. {
  35. cerr << "Stopping work\n";
  36. if (wrkctrlstate.worker_thread_state != WT_NOT_RUNNING) {
  37. // Tell the worker thread to stop after its next kernel launch
  38. wrkctrlstate.worker_thread_state = WT_SHOULD_STOP;
  39. pthread_join(wrkctrlstate.worker_thread, NULL);
  40. wrkctrlstate.worker_thread_state = WT_NOT_RUNNING;
  41. }
  42. // Close the connections to the dpnodes
  43. vector<struct bufferevent *>::iterator bevit;
  44. for (bevit = wrkctrlstate.dpnodes.begin();
  45. bevit != wrkctrlstate.dpnodes.end(); ++bevit) {
  46. bufferevent_free(*bevit);
  47. }
  48. wrkctrlstate.dpnodes.clear();
  49. wrkctrlstate.num_connected_dpnodes = 0;
  50. wrkctrlstate.num_expected_dpnodes = 0;
  51. // Careful! Subproblem uses NTL, so we must be sure we're not
  52. // multithreaded at this point.
  53. delete wrkctrlstate.current_problem;
  54. wrkctrlstate.current_problem = NULL;
  55. }
  56. static void start_working(void)
  57. {
  58. cerr << "Starting work\n";
  59. }
  60. static void dpconn_event_cb(struct bufferevent *bev, short events,
  61. void *ctx)
  62. {
  63. if (events & BEV_EVENT_CONNECTED) {
  64. // We have successfully connected to the dpnode
  65. ++wrkctrlstate.num_connected_dpnodes;
  66. if (wrkctrlstate.num_connected_dpnodes ==
  67. wrkctrlstate.num_expected_dpnodes) {
  68. start_working();
  69. }
  70. } else if (events & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
  71. fprintf(stderr, "Closing connection to dpnode\n");
  72. bufferevent_free(bev);
  73. stop_working();
  74. }
  75. }
  76. static void controllerconn_reader(struct bufferevent *bev, void *ctx)
  77. {
  78. struct evbuffer *input = bufferevent_get_input(bev);
  79. WrkControllerConnInfo *info = (WrkControllerConnInfo *)ctx;
  80. unsigned char cmd[1];
  81. unsigned char subproblem[SUBPROBLEM_DESC_LEN];
  82. while(1) {
  83. size_t len = evbuffer_get_length(input);
  84. switch(info->state) {
  85. case WRKCCSTATE_AWAITCMD:
  86. if (len < 1) return;
  87. bufferevent_read(bev, cmd, 1);
  88. switch(cmd[0]) {
  89. case 'P':
  90. info->state = WRKCCSTATE_RDPROBLEM;
  91. break;
  92. case 'S':
  93. stop_working();
  94. break;
  95. default:
  96. /* Unknown command received */
  97. fprintf(stderr, "Unknown command in "
  98. "controllerconn_reader: %c\n", cmd[0]);
  99. info->state = WRKCCSTATE_END;
  100. break;
  101. }
  102. break;
  103. case WRKCCSTATE_RDPROBLEM:
  104. if (len < SUBPROBLEM_DESC_LEN+2) return;
  105. stop_working();
  106. bufferevent_read(bev, subproblem, SUBPROBLEM_DESC_LEN);
  107. bufferevent_read(bev, &(info->num_dpnodes), 2);
  108. // Careful! Subproblem uses NTL, so we must be sure
  109. // we're not multithreaded at this point.
  110. wrkctrlstate.current_problem = new Subproblem(subproblem);
  111. info->state = WRKCCSTATE_RDDPNODES;
  112. /* FALLTHROUGH */
  113. case WRKCCSTATE_RDDPNODES:
  114. if (len < 6*(info->num_dpnodes)) return;
  115. wrkctrlstate.num_expected_dpnodes = info->num_dpnodes;
  116. {
  117. unsigned short i;
  118. for(i=0;i<info->num_dpnodes;++i) {
  119. unsigned char ipport[6];
  120. bufferevent_read(bev, ipport, 6);
  121. cerr << "Connecting to DPnode " <<
  122. int(ipport[0]) << "." <<
  123. int(ipport[1]) << "." <<
  124. int(ipport[2]) << "." <<
  125. int(ipport[3]) << ":" <<
  126. ((ipport[4] << 8) + ipport[5]) <<
  127. "\n";
  128. struct bufferevent *dpbev = client_create(
  129. bufferevent_get_base(bev), ipport,
  130. dpconn_event_cb);
  131. if (dpbev) {
  132. wrkctrlstate.dpnodes.push_back(dpbev);
  133. } else {
  134. stop_working();
  135. }
  136. }
  137. }
  138. info->state = WRKCCSTATE_AWAITCMD;
  139. break;
  140. case WRKCCSTATE_END:
  141. // Shut down
  142. delete info;
  143. event_base_loopbreak(bufferevent_get_base(bev));
  144. bufferevent_free(bev);
  145. return;
  146. }
  147. }
  148. }
  149. static void controllerconn_event_cb(struct bufferevent *bev, short events,
  150. void *ctx)
  151. {
  152. if (events & BEV_EVENT_CONNECTED) {
  153. // We have successfully connected to the controller
  154. char id[1] = { 'W' };
  155. bufferevent_enable(bev, EV_READ|EV_WRITE);
  156. bufferevent_write(bev, id, 1);
  157. bufferevent_setcb(bev, controllerconn_reader, NULL,
  158. controllerconn_event_cb, new WrkControllerConnInfo());
  159. } else if (events & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
  160. fprintf(stderr, "Closing connection to controller and exiting\n");
  161. event_base_loopbreak(bufferevent_get_base(bev));
  162. bufferevent_free(bev);
  163. }
  164. }
  165. int main(int argc, char **argv)
  166. {
  167. if (argc != 3) {
  168. fprintf(stderr, "Usage: %s controller_host controller_port\n", argv[0]);
  169. return 1;
  170. }
  171. unsigned short controller_port = strtoul(argv[2], NULL, 10);
  172. return controller_client(argv[1], controller_port,
  173. controllerconn_event_cb);
  174. }