void Receiver::execute(AsyncSession& session, bool /*isRetry*/) { SubscriptionManager subs(session); subscription = subs.subscribe(*this, queue, settings); subs.run(); if (settings.autoAck) { subscription.accept(subscription.getUnaccepted()); } }
void receivedFromSource(Message& message) { QPID_LOG(debug, "transfering " << (transfered+1) << " of " << expected); message.getDeliveryProperties().setRoutingKey(destination); async(sourceSubscription.getSession()).messageTransfer(arg::content=message); if (++transfered == expected) { QPID_LOG(info, "completed job: " << transfered << " messages shifted from " << source << " to " << destination); sourceSubscription.accept(sourceSubscription.getUnaccepted()); sourceSubscription.getSession().txCommit(); sourceSubscription.cancel(); //grant credit to allow broker to send us another control message controlSubscription.grantMessageCredit(1); } }
void run() { // Subscribe try { if (opts.txSub) sync(session).txSelect(); SubscriptionManager subs(session); SubscriptionSettings settings; settings.autoAck = opts.txSub ? opts.txSub : opts.ack; settings.acceptMode = (opts.txSub || opts.ack ? ACCEPT_MODE_EXPLICIT : ACCEPT_MODE_NONE); settings.flowControl = FlowControl::messageCredit(opts.subQuota); LocalQueue lq; Subscription subscription = subs.subscribe(lq, queue, settings); // Notify controller we are ready. session.messageTransfer(arg::content=Message("ready", fqn("sub_ready")), arg::acceptMode=1); if (opts.txSub) { if (opts.commitAsync) session.txCommit(); else sync(session).txCommit(); } LocalQueue iterationControl; if (opts.iterations > 1) { subs.subscribe(iterationControl, fqn("sub_iteration"), SubscriptionSettings(FlowControl::messageCredit(0))); } for (size_t j = 0; j < opts.iterations; ++j) { if (j > 0) { //need to wait here until all subs are done session.messageFlow(fqn("sub_iteration"), 0, 1); iterationControl.pop(); //need to allocate some more credit for subscription session.messageFlow(queue, 0, opts.subQuota); } Message msg; AbsTime start=now(); size_t expect=0; for (size_t i = 0; i < opts.subQuota; ++i) { msg=lq.pop(); if (opts.txSub && ((i+1) % opts.txSub == 0)) { if (opts.commitAsync) session.txCommit(); else sync(session).txCommit(); } if (opts.intervalSub) qpid::sys::usleep(opts.intervalSub*1000); // TODO aconway 2007-11-23: check message order for. // multiple publishers. Need an array of counters, // one per publisher and a publisher ID in the // message. Careful not to introduce a lot of overhead // here, e.g. no std::map, std::string etc. // // For now verify order only for a single publisher. size_t offset = opts.uniqueData ? 5 /*marker is 'data:'*/ : 0; size_t n; memcpy (&n, reinterpret_cast<const char*>(msg.getData().data() + offset), sizeof(n)); if (opts.pubs == 1) { if (opts.subs == 1 || opts.mode == FANOUT) verify(n==expect, "==", expect, n); else verify(n>=expect, ">=", expect, n); expect = n+1; } } if (opts.txSub || opts.ack) subscription.accept(subscription.getUnaccepted()); if (opts.txSub) { if (opts.commitAsync) session.txCommit(); else sync(session).txCommit(); } AbsTime end=now(); // Report to publisher. Message result(lexical_cast<string>(opts.subQuota/secs(start,end)), fqn("sub_done")); session.messageTransfer(arg::content=result, arg::acceptMode=1); if (opts.txSub) sync(session).txCommit(); } session.close(); } catch (const std::exception& e) { cout << "SubscribeThread exception: " << e.what() << endl; } }