// The worker thread function. // // worker - The worker. // // Returns 0 if successful. void *sky_worker_run(void *_worker) { int rc; uint32_t i; sky_worker *worker = (sky_worker*)_worker; sky_worklet *worklet = NULL; check(worker != NULL, "Worker required"); // Start benchmark. struct timeval tv; gettimeofday(&tv, NULL); int64_t t0 = (tv.tv_sec*1000) + (tv.tv_usec/1000); // Read data from stream. if(worker->read != NULL) { rc = worker->read(worker, worker->input); check(rc == 0, "Worker unable to read from stream"); } // Push a message to each servlet. for(i=0; i<worker->push_socket_count; i++) { worklet = sky_worklet_create(worker); check_mem(worklet); rc = sky_zmq_send_ptr(worker->push_sockets[i], &worklet); check(rc == 0, "Worker unable to send worklet"); } // Read in one pull message for every push message sent. for(i=0; i<worker->push_socket_count; i++) { // Receive worker back from servlet. rc = sky_zmq_recv_ptr(worker->pull_socket, (void**)&worklet); check(rc == 0 && worklet != NULL, "Worker unable to receive worklet"); // Reduce worklet. if(worker->reduce != NULL) { rc = worker->reduce(worker, worklet->data); check(rc == 0, "Worker unable to reduce"); } // Free worklet. if(worker->map_free) worker->map_free(worklet->data); worklet->data = NULL; sky_worklet_free(worklet); worklet = NULL; } // Output data to stream. if(worker->write != NULL) { rc = worker->write(worker, worker->output); check(rc == 0, "Worker unable to write output"); } // End benchmark. gettimeofday(&tv, NULL); int64_t t1 = (tv.tv_sec*1000) + (tv.tv_usec/1000); printf("[worker] t=%.3fs\n", ((float)(t1-t0))/1000); // Clean up worker. worker->free(worker); sky_worker_free(worker); return NULL; error: sky_worker_free(worker); return NULL; }
// Sends a shutdown signal to all servlets and waits for their confirmation // before returning. // // server - The server. // table - The table to close servlets for. Or NULL if all servlets should be // closed. // // Returns 0 if successful, otherwise returns -1. int sky_server_stop_servlets(sky_server *server, sky_table *table) { int rc; void *pull_socket = NULL; void *push_socket = NULL; assert(server != NULL); // Create pull socket. pull_socket = zmq_socket(server->context, ZMQ_PULL); check(pull_socket != NULL, "Unable to create server shutdown socket"); // Bind pull socket. rc = zmq_bind(pull_socket, SKY_SERVER_SHUTDOWN_URI); check(rc == 0, "Unable to bind server shutdown socket"); // Send a shutdown message to each servlet. uint32_t i, j; uint32_t count = 0; for(i=0; i<server->servlet_count; i++) { // Check if this servlet matches the table. if(table == NULL || server->servlets[i]->tablet->table == table) { // Create push socket. push_socket = zmq_socket(server->context, ZMQ_PUSH); check(push_socket != NULL, "Unable to create shutdown push socket"); // Connect to servlet. rc = zmq_connect(push_socket, bdata(server->servlets[i]->uri)); check(rc == 0, "Unable to connect to servlet for shutdown"); // Send NULL worklet for shutdown. void *ptr = NULL; rc = sky_zmq_send_ptr(push_socket, &ptr); check(rc == 0, "Unable to send worklet message"); // Close socket. rc = zmq_close(push_socket); check(rc == 0, "Unable to close server shutdown push socket"); push_socket = NULL; // Clear the servlet. for(j=i+1; j<server->servlet_count; j++) { server->servlets[j-1] = server->servlets[j]; } server->servlets[server->servlet_count-1] = NULL; server->servlet_count--; i--; // Increment the counter. count++; } } // Read in one pull message for every push message sent. for(i=0; i<count; i++) { // Receive servlet ref on shutdown. sky_servlet *servlet = NULL; rc = sky_zmq_recv_ptr(pull_socket, (void**)&servlet); check(rc == 0, "Server unable to receive shutdown response"); } // Clean up socket. rc = zmq_close(pull_socket); check(rc == 0, "Unable to close server shutdown pull socket"); // Clean up servlets. if(server->servlet_count == 0) { free(server->servlets); server->servlets = NULL; } return 0; error: if(pull_socket) zmq_close(pull_socket); if(push_socket) zmq_close(push_socket); return -1; }