void *fetch_thread(void * arg) { struct request_queue * queue = (struct request_queue *)arg; struct item * item; enum protoCmd res; for (int i = 0; i < NO_QUEUE_REQUESTS; i++) { item = request_queue_fetch_request(queue); } }
/** * This function is used as a the start function for the slave renderer thread. * It pulls a request from the central queue of requests and dispatches it to * the slave renderer. It then blocks and waits for the response with no timeout. * As it only sends one request at a time (there are as many slave_thread threads as there * are rendering threads on the slaves) nothing gets queued on the slave and should get * rendererd immediately. Thus overall, requests should be nicely load balanced between * all the rendering threads available both locally and in the slaves. */ void *slave_thread(void * arg) { renderd_config * sConfig = (renderd_config *) arg; int pfd = FD_INVALID; int retry; size_t ret_size; struct protocol * resp; struct protocol * req_slave; req_slave = (struct protocol *)malloc(sizeof(struct protocol)); resp = (struct protocol *)malloc(sizeof(struct protocol)); bzero(req_slave, sizeof(struct protocol)); bzero(resp, sizeof(struct protocol)); while (1) { if (pfd == FD_INVALID) { pfd = client_socket_init(sConfig); if (pfd == FD_INVALID) { if (sConfig->ipport > 0) { syslog(LOG_ERR, "Failed to connect to render slave %s:%i, trying again in 30 seconds", sConfig->iphostname, sConfig->ipport); } else { syslog( LOG_ERR, "Failed to connect to render slave %s, trying again in 30 seconds", sConfig->socketname); } sleep(30); continue; } } enum protoCmd ret; struct item *item = request_queue_fetch_request(render_request_queue); if (item) { struct protocol *req = &item->req; req_slave->ver = PROTO_VER; req_slave->cmd = cmdRender; strcpy(req_slave->xmlname, req->xmlname); strcpy(req_slave->mimetype, req->mimetype); strcpy(req_slave->options, req->options); req_slave->x = req->x; req_slave->y = req->y; req_slave->z = req->z; /*Dispatch request to slave renderd*/ retry = 2; syslog(LOG_INFO, "Dispatching request to slave thread on fd %i", pfd); do { ret_size = send_cmd(req_slave, pfd); if (ret_size == sizeof(struct protocol)) { //correctly sent command to slave break; } if (errno != EPIPE) { syslog(LOG_ERR, "Failed to send cmd to render slave, shutting down thread"); free(resp); free(req_slave); close(pfd); return NULL; } syslog(LOG_WARNING, "Failed to send cmd to render slave, retrying"); close(pfd); pfd = client_socket_init(sConfig); if (pfd == FD_INVALID) { syslog(LOG_ERR, "Failed to re-connect to render slave, dropping request"); ret = cmdNotDone; send_response(item, ret, -1); break; } } while (retry--); if (pfd == FD_INVALID || ret_size != sizeof(struct protocol)) { continue; } ret_size = 0; retry = 10; while ((ret_size < sizeof(struct protocol)) && (retry > 0)) { ret_size = recv(pfd, resp + ret_size, (sizeof(struct protocol) - ret_size), 0); if ((errno == EPIPE) || ret_size == 0) { close(pfd); pfd = FD_INVALID; ret_size = 0; syslog(LOG_ERR, "Pipe to render slave closed"); break; } retry--; } if (ret_size < sizeof(struct protocol)) { if (sConfig->ipport > 0) { syslog( LOG_ERR, "Invalid reply from render slave %s:%i, trying again in 30 seconds", sConfig->iphostname, sConfig->ipport); } else { syslog( LOG_ERR, "Invalid reply render slave %s, trying again in 30 seconds", sConfig->socketname); } ret = cmdNotDone; send_response(item, ret, -1); sleep(30); } else { ret = resp->cmd; send_response(item, ret, -1); if (resp->cmd != cmdDone) { if (sConfig->ipport > 0) { syslog( LOG_ERR, "Request from render slave %s:%i did not complete correctly", sConfig->iphostname, sConfig->ipport); } else { syslog( LOG_ERR, "Request from render slave %s did not complete correctly", sConfig->socketname); } //Sleep for a while to make sure we don't overload the renderer //This only happens if it didn't correctly block on the rendering //request sleep(30); } } } else { sleep(1); // TODO: Use an event to indicate there are new requests } } free(resp); free(req_slave); return NULL; }