void blocking_actor::dequeue(behavior& bhvr, message_id mid) { CAF_LOG_TRACE(CAF_MARG(mid, integer_value)); // try to dequeue from cache first if (invoke_from_cache(bhvr, mid)) { return; } // requesting an invalid timeout will reset our active timeout uint32_t timeout_id = 0; if (mid == invalid_message_id) { timeout_id = request_timeout(bhvr.timeout()); } else { request_sync_timeout_msg(bhvr.timeout(), mid); } // read incoming messages for (;;) { await_data(); auto msg = next_message(); switch (invoke_message(msg, bhvr, mid)) { case im_success: if (mid == invalid_message_id) { reset_timeout(timeout_id); } return; case im_skipped: if (msg) { push_to_cache(std::move(msg)); } break; default: // delete msg break; } } }
void blocking_actor::dequeue(behavior& bhvr, message_id mid) { // try to dequeue from cache first if (invoke_from_cache(bhvr, mid)) { return; } // requesting an invalid timeout will reset our active timeout auto timeout_id = request_timeout(bhvr.timeout()); // read incoming messages for (;;) { await_data(); auto msg = next_message(); switch (invoke_message(msg, bhvr, mid)) { case im_success: reset_timeout(timeout_id); return; case im_skipped: if (msg) { push_to_cache(std::move(msg)); } break; default: // delete msg break; } } }
static void cmdBroadcast(void *base) { node_t *node = (node_t *) base; queue_t *q = NULL; message_t *msg; assert(node); assert(node->handle >= 0); assert(node->sysdata); logger(node->sysdata->logging, 3, "node:%d BROADCAST (flags:%x, mask:%x)", node->handle, node->data.flags, node->data.mask); // do we have a queue name, or a qid? if (BIT_TEST(node->data.mask, DATA_MASK_QUEUE) || BIT_TEST(node->data.mask, DATA_MASK_QUEUEID)) { if (BIT_TEST(node->data.mask, DATA_MASK_QUEUE)) { q = queue_get_name(node->sysdata->queues, expbuf_string(&node->data.queue)); } else if (BIT_TEST(node->data.mask, DATA_MASK_QUEUEID)) { q = queue_get_id(node->sysdata->queues, node->data.qid); } if (q == NULL) { q = queue_create(node->sysdata, expbuf_string(&node->data.queue)); } // by this point, we should have 'q'. assert(q); // create message object. msg = next_message(node); assert(msg); // now that we have a message structure completely filled out with the // data from the node, then we need to do something with it. assert(0); } else { // we didn't have a queue name, or a queue id. We need to handle this gracefully. assert(0); } }
/* * Print the current active headings. * Don't change dot if invoker didn't give an argument. */ PUBLIC int headers(void *v) { int *msgvec; int n; int flag; struct message *mp; int size; msgvec = v; size = screensize(); n = msgvec[0]; if (n != 0) screen = (n - 1)/size; if (screen < 0) screen = 0; if ((mp = get_message(screen * size + 1)) == NULL) { int msgCount; msgCount = get_msgCount(); if (screen * size + 1 > msgCount) mp = get_message(msgCount - size + 1); if (mp == NULL) mp = get_message(1); } flag = 0; if (dot != get_message(n)) dot = mp; for (/*EMPTY*/; mp; mp = next_message(mp)) { if (mp->m_flag & MDELETED) continue; if (flag++ >= size) break; printhead(get_msgnum(mp)); } if (flag == 0) { (void)printf("No more mail.\n"); return 1; } return 0; }
/** * Close GOSS channel. */ void gridpack::goss::GOSSUtils::closeGOSSChannel(gridpack::parallel::Communicator &comm) { if (GA_Pgroup_nodeid(p_grp) == 0) { // Send final message indicating the channel is being closed #ifndef GOSS_DEBUG std::string buf = "_goss_channel_closed"; std::auto_ptr<TextMessage> message(p_session->createTextMessage(buf)); p_producer->send(message.get()); gridpack::utility::CoarseTimer *timer = gridpack::utility::CoarseTimer::instance(); char sbuf[256]; sprintf(sbuf,"_goss_channel_closed topic: %s %f",p_current_topic.c_str(), timer->currentTime()); printf("%s\n",sbuf); std::string acknowledge_topic("topic.goss.gridpack."); acknowledge_topic.append(p_current_topic); acknowledge_topic.append(".acknowledge"); printf("_goss_channel_ack: %s\n",acknowledge_topic.c_str()); std::auto_ptr<Destination> dest(p_session->createTopic(acknowledge_topic)); std::auto_ptr<MessageConsumer> consumer(p_session->createConsumer(dest.get())); std::cout << "Waiting for messages..."<<std::endl; std::auto_ptr<Message> next_message(consumer->receive()); const TextMessage *txtMsg = dynamic_cast<const TextMessage*>(next_message.get()); if (txtMsg->getText() != "success") { std::cout << "Message failure: "<<txtMsg->getText()<<std::endl; } if (p_connection) delete p_connection; if (p_session) delete p_session; if (p_destination) delete p_destination; if (p_producer) delete p_producer; #endif p_open = false; } }
resumable::resume_result resume(detail::cs_thread*, execution_unit* host) override { auto d = static_cast<Derived*>(this); d->m_host = host; CPPA_LOG_TRACE("id = " << d->id()); auto done_cb = [&]() -> bool { CPPA_LOG_TRACE(""); d->bhvr_stack().clear(); d->bhvr_stack().cleanup(); d->on_exit(); if (!d->bhvr_stack().empty()) { CPPA_LOG_DEBUG("on_exit did set a new behavior in on_exit"); d->planned_exit_reason(exit_reason::not_exited); return false; // on_exit did set a new behavior } auto rsn = d->planned_exit_reason(); if (rsn == exit_reason::not_exited) { rsn = exit_reason::normal; d->planned_exit_reason(rsn); } d->cleanup(rsn); return true; }; auto actor_done = [&] { return d->bhvr_stack().empty() || d->planned_exit_reason() != exit_reason::not_exited; }; // actors without behavior or that have already defined // an exit reason must not be resumed CPPA_REQUIRE(!d->m_initialized || !actor_done()); if (!d->m_initialized) { d->m_initialized = true; auto bhvr = d->make_behavior(); if (bhvr) d->become(std::move(bhvr)); // else: make_behavior() might have just called become() if (actor_done() && done_cb()) return resume_result::done; // else: enter resume loop } try { for (;;) { auto ptr = d->next_message(); if (ptr) { if (d->invoke_message(ptr)) { if (actor_done() && done_cb()) { CPPA_LOG_DEBUG("actor exited"); return resume_result::done; } // continue from cache if current message was // handled, because the actor might have changed // its behavior to match 'old' messages now while (d->invoke_message_from_cache()) { if (actor_done() && done_cb()) { CPPA_LOG_DEBUG("actor exited"); return resume_result::done; } } } // add ptr to cache if invoke_message // did not reset it (i.e. skipped, but not dropped) if (ptr) { CPPA_LOG_DEBUG("add message to cache"); d->push_to_cache(std::move(ptr)); } } else { CPPA_LOG_DEBUG("no more element in mailbox; " "going to block"); if (d->mailbox().try_block()) { return resumable::resume_later; } // else: try again } } } catch (actor_exited& what) { CPPA_LOG_INFO("actor died because of exception: actor_exited, " "reason = " << what.reason()); if (d->exit_reason() == exit_reason::not_exited) { d->quit(what.reason()); } } catch (std::exception& e) { CPPA_LOG_WARNING("actor died because of exception: " << detail::demangle(typeid(e)) << ", what() = " << e.what()); if (d->exit_reason() == exit_reason::not_exited) { d->quit(exit_reason::unhandled_exception); } } catch (...) { CPPA_LOG_WARNING("actor died because of an unknown exception"); if (d->exit_reason() == exit_reason::not_exited) { d->quit(exit_reason::unhandled_exception); } } done_cb(); return resumable::done; }
/* Verify received requests and take the necessary actions (return a response, kill the connection ...) */ static apr_status_t replay(serv_ctx_t *servctx, apr_int16_t rtnevents, apr_pool_t *pool) { apr_status_t status = APR_SUCCESS; test_server_action_t *action; if (rtnevents & APR_POLLIN) { if (servctx->message_list == NULL) { /* we're not expecting any requests to reach this server! */ serf__log(TEST_VERBOSE, __FILE__, "Received request where none was expected.\n"); return SERF_ERROR_ISSUE_IN_TESTSUITE; } if (servctx->cur_action >= servctx->action_count) { char buf[128]; apr_size_t len = sizeof(buf); status = servctx->read(servctx, buf, &len); if (! APR_STATUS_IS_EAGAIN(status)) { /* we're out of actions! */ serf__log(TEST_VERBOSE, __FILE__, "Received more requests than expected.\n"); return SERF_ERROR_ISSUE_IN_TESTSUITE; } return status; } action = &servctx->action_list[servctx->cur_action]; serf__log(TEST_VERBOSE, __FILE__, "POLLIN while replaying action %d, kind: %d.\n", servctx->cur_action, action->kind); /* Read the remaining data from the client and kill the socket. */ if (action->kind == SERVER_IGNORE_AND_KILL_CONNECTION) { char buf[128]; apr_size_t len = sizeof(buf); status = servctx->read(servctx, buf, &len); if (status == APR_EOF) { serf__log(TEST_VERBOSE, __FILE__, "Killing this connection.\n"); apr_socket_close(servctx->client_sock); servctx->client_sock = NULL; next_action(servctx); return APR_SUCCESS; } return status; } else if (action->kind == SERVER_RECV || (action->kind == SERVER_RESPOND && servctx->outstanding_responses == 0)) { apr_size_t msg_len, len; char buf[128]; test_server_message_t *message; message = &servctx->message_list[servctx->cur_message]; msg_len = strlen(message->text); do { len = msg_len - servctx->message_buf_pos; if (len > sizeof(buf)) len = sizeof(buf); status = servctx->read(servctx, buf, &len); if (SERF_BUCKET_READ_ERROR(status)) return status; if (status == APR_EOF) { serf__log(TEST_VERBOSE, __FILE__, "Server: Client hung up the connection.\n"); break; } if (servctx->options & TEST_SERVER_DUMP) fwrite(buf, len, 1, stdout); if (strncmp(buf, message->text + servctx->message_buf_pos, len) != 0) { /* ## TODO: Better diagnostics. */ printf("Expected: (\n"); fwrite(message->text + servctx->message_buf_pos, len, 1, stdout); printf(")\n"); printf("Actual: (\n"); fwrite(buf, len, 1, stdout); printf(")\n"); return SERF_ERROR_ISSUE_IN_TESTSUITE; } servctx->message_buf_pos += len; if (servctx->message_buf_pos >= msg_len) { next_message(servctx); servctx->message_buf_pos -= msg_len; if (action->kind == SERVER_RESPOND) servctx->outstanding_responses++; if (action->kind == SERVER_RECV) next_action(servctx); break; } } while (!status); } else if (action->kind == PROXY_FORWARD) { apr_size_t len; char buf[BUFSIZE]; serf_bucket_t *tmp; /* Read all incoming data from the client to forward it to the server later. */ do { len = BUFSIZE; status = servctx->read(servctx, buf, &len); if (SERF_BUCKET_READ_ERROR(status)) return status; serf__log(TEST_VERBOSE, __FILE__, "proxy: reading %d bytes %.*s from client with " "status %d.\n", len, len, buf, status); if (status == APR_EOF) { serf__log(TEST_VERBOSE, __FILE__, "Proxy: client hung up the connection. Reset the " "connection to the server.\n"); /* We have to stop forwarding, if a new connection opens the CONNECT request should not be forwarded to the server. */ next_action(servctx); } if (!servctx->servstream) servctx->servstream = serf__bucket_stream_create( servctx->allocator, detect_eof,servctx); if (len) { tmp = serf_bucket_simple_copy_create(buf, len, servctx->allocator); serf_bucket_aggregate_append(servctx->servstream, tmp); } } while (!status); } } if (rtnevents & APR_POLLOUT) { action = &servctx->action_list[servctx->cur_action]; serf__log(TEST_VERBOSE, __FILE__, "POLLOUT when replaying action %d, kind: %d.\n", servctx->cur_action, action->kind); if (action->kind == SERVER_RESPOND && servctx->outstanding_responses) { apr_size_t msg_len; apr_size_t len; msg_len = strlen(action->text); len = msg_len - servctx->action_buf_pos; status = servctx->send(servctx, action->text + servctx->action_buf_pos, &len); if (status != APR_SUCCESS) return status; if (servctx->options & TEST_SERVER_DUMP) fwrite(action->text + servctx->action_buf_pos, len, 1, stdout); servctx->action_buf_pos += len; if (servctx->action_buf_pos >= msg_len) { next_action(servctx); servctx->outstanding_responses--; } } else if (action->kind == SERVER_KILL_CONNECTION || action->kind == SERVER_IGNORE_AND_KILL_CONNECTION) { serf__log(TEST_VERBOSE, __FILE__, "Killing this connection.\n"); apr_socket_close(servctx->client_sock); servctx->client_sock = NULL; next_action(servctx); } else if (action->kind == PROXY_FORWARD) { apr_size_t len; char *buf; if (!servctx->proxy_client_sock) { serf__log(TEST_VERBOSE, __FILE__, "Proxy: setting up connection " "to server.\n"); status = create_client_socket(&servctx->proxy_client_sock, servctx, action->text); if (!servctx->clientstream) servctx->clientstream = serf__bucket_stream_create( servctx->allocator, detect_eof,servctx); } /* Send all data received from the server to the client. */ do { apr_size_t readlen; readlen = BUFSIZE; status = serf_bucket_read(servctx->clientstream, readlen, &buf, &readlen); if (SERF_BUCKET_READ_ERROR(status)) return status; if (!readlen) break; len = readlen; serf__log(TEST_VERBOSE, __FILE__, "proxy: sending %d bytes to client.\n", len); status = servctx->send(servctx, buf, &len); if (status != APR_SUCCESS) { return status; } if (len != readlen) /* abort for now, return buf to aggregate if not everything could be sent. */ return APR_EGENERAL; } while (!status); } } else if (rtnevents & APR_POLLIN) { /* ignore */ } else { printf("Unknown rtnevents: %d\n", rtnevents); abort(); } return status; }
resumable::resume_result resume(execution_unit* new_host, size_t max_throughput) override { CAF_REQUIRE(max_throughput > 0); auto d = static_cast<Derived*>(this); CAF_LOG_TRACE("id = " << d->id()); d->host(new_host); auto done_cb = [&]() -> bool { CAF_LOG_TRACE(""); d->bhvr_stack().clear(); d->bhvr_stack().cleanup(); d->on_exit(); if (!d->bhvr_stack().empty()) { CAF_LOG_DEBUG("on_exit did set a new behavior"); d->planned_exit_reason(exit_reason::not_exited); return false; // on_exit did set a new behavior } auto rsn = d->planned_exit_reason(); if (rsn == exit_reason::not_exited) { rsn = exit_reason::normal; d->planned_exit_reason(rsn); } d->cleanup(rsn); return true; }; auto actor_done = [&]() -> bool { if (d->bhvr_stack().empty() || d->planned_exit_reason() != exit_reason::not_exited) { return done_cb(); } return false; }; // actors without behavior or that have already defined // an exit reason must not be resumed CAF_REQUIRE(!d->is_initialized() || (!d->bhvr_stack().empty() && d->planned_exit_reason() == exit_reason::not_exited)); std::exception_ptr eptr = nullptr; try { if (!d->is_initialized()) { CAF_LOG_DEBUG("initialize actor"); d->is_initialized(true); auto bhvr = d->make_behavior(); CAF_LOG_DEBUG_IF(!bhvr, "make_behavior() did not return a behavior, " << "bhvr_stack().empty() = " << std::boolalpha << d->bhvr_stack().empty()); if (bhvr) { // make_behavior() did return a behavior instead of using become() CAF_LOG_DEBUG("make_behavior() did return a valid behavior"); d->become(std::move(bhvr)); } if (actor_done()) { CAF_LOG_DEBUG("actor_done() returned true right " << "after make_behavior()"); return resume_result::done; } } // max_throughput = 0 means infinite for (size_t i = 0; i < max_throughput; ++i) { auto ptr = d->next_message(); if (ptr) { if (d->invoke_message(ptr)) { if (actor_done()) { CAF_LOG_DEBUG("actor exited"); return resume_result::done; } // continue from cache if current message was // handled, because the actor might have changed // its behavior to match 'old' messages now while (d->invoke_message_from_cache()) { if (actor_done()) { CAF_LOG_DEBUG("actor exited"); return resume_result::done; } } } // add ptr to cache if invoke_message // did not reset it (i.e. skipped, but not dropped) if (ptr) { CAF_LOG_DEBUG("add message to cache"); d->push_to_cache(std::move(ptr)); } } else { CAF_LOG_DEBUG("no more element in mailbox; going to block"); if (d->mailbox().try_block()) { return resumable::awaiting_message; } CAF_LOG_DEBUG("try_block() interrupted by new message"); } } if (!d->has_next_message() && d->mailbox().try_block()) { return resumable::awaiting_message; } // time's up return resumable::resume_later; } catch (actor_exited& what) { CAF_LOG_INFO("actor died because of exception: actor_exited, " "reason = " << what.reason()); if (d->exit_reason() == exit_reason::not_exited) { d->quit(what.reason()); } } catch (std::exception& e) { CAF_LOG_INFO("actor died because of an exception: " << detail::demangle(typeid(e)) << ", what() = " << e.what()); if (d->exit_reason() == exit_reason::not_exited) { d->quit(exit_reason::unhandled_exception); } eptr = std::current_exception(); } catch (...) { CAF_LOG_INFO("actor died because of an unknown exception"); if (d->exit_reason() == exit_reason::not_exited) { d->quit(exit_reason::unhandled_exception); } eptr = std::current_exception(); } if (eptr) { auto opt_reason = d->handle(eptr); if (opt_reason) { // use exit reason defined by custom handler d->planned_exit_reason(*opt_reason); } } if (!actor_done()) { // actor has been "revived", try running it again later return resumable::resume_later; } return resumable::done; }
//----------------------------------------------------------------------------- // A request has been received for a queue. We need take it and pass it to a // node that can handle the request. static void cmdRequest(void *base) { node_t *node = (node_t *) base; message_t *msg; queue_t *q; stats_t *stats; assert(node); assert(node->handle >= 0); assert(node->sysdata); logger(node->sysdata->logging, 3, "node:%d REQUEST (flags:%x, mask:%x)", node->handle, node->data.flags, node->data.mask); assert(node->sysdata->queues); assert(node->sysdata->bufpool); // make sure we have the required data. At least payload, and a queueid or queue. if (BIT_TEST(node->data.mask, DATA_MASK_PAYLOAD) && (BIT_TEST(node->data.mask, DATA_MASK_QUEUE) || BIT_TEST(node->data.mask, DATA_MASK_QUEUEID))) { // create the message object to hold the data. assert(node->sysdata->msg_list); msg = next_message(node); assert(msg); // The node should have received a payload command. It would have been // assigned to an appropriate buffer. We need to move that buffer to the // message, where it will be handled from there. assert(node->data.payload); assert(msg->data == NULL); msg->data = node->data.payload; node->data.payload = NULL; // if message is NOREPLY, then we dont need some bits. However, we will need to send a DELIVERED. if (BIT_TEST(node->data.flags, DATA_FLAG_NOREPLY)) { BIT_SET(msg->flags, FLAG_MSG_NOREPLY); assert(msg->source_id == 0); // the source_node would have been set when the message object was // obtained. But since we dont want it in this mode, we set it to // NULL. assert(msg->source_node != NULL); msg->source_node = NULL; assert(BIT_TEST(node->data.mask, DATA_MASK_ID)); sendDelivered(node, node->data.id); } else { assert(BIT_TEST(msg->flags, FLAG_MSG_NOREPLY) == 0); // make a note in the msg object, the source node. If a reply is // expected, a messageid should also have been supplied, use that for // the node_side. assert(msg->source_node == node); assert(BIT_TEST(node->data.mask, DATA_MASK_ID)); message_set_origid(msg, node->data.id); } if (BIT_TEST(node->data.mask, DATA_MASK_TIMEOUT)) { // set the timeout... message_set_timeout(msg, node->data.timeout); } // find the q object for this queue. if (BIT_TEST(node->data.mask, DATA_MASK_QUEUE)) { q = queue_get_name(node->sysdata->queues, expbuf_string(&node->data.queue)); } else if (BIT_TEST(node->data.mask, DATA_MASK_QUEUEID)) { q = queue_get_id(node->sysdata->queues, node->data.qid); } else { assert(0); } if (q == NULL) { // we dont have a queue, so we will need to create one. q = queue_create(node->sysdata, expbuf_string(&node->data.queue)); } assert(q); assert(ll_count(node->sysdata->queues) > 0); // add the message to the queue. logger(node->sysdata->logging, 2, "processRequest: node:%d, msg_id:%d, q:%d", node->handle, msg->id, q->qid); assert(q->sysdata); queue_addmsg(q, msg); stats = node->sysdata->stats; assert(stats); stats->requests ++; } else { // required data was not found. // need to return some sort of error assert(0); } }