Skip to content

Commit

Permalink
Add tx_recv file
Browse files Browse the repository at this point in the history
  • Loading branch information
DreamPearl committed Dec 3, 2024
1 parent eb4514b commit fa9236d
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 52 deletions.
3 changes: 2 additions & 1 deletion cpp/examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ foreach(example
service_bus
multithreaded_client
multithreaded_client_flow_control
tx_send)
tx_send
tx_recv)
add_executable(${example} ${example}.cpp)
target_link_libraries(${example} Proton::cpp Threads::Threads)
endforeach()
Expand Down
2 changes: 1 addition & 1 deletion cpp/examples/simple_recv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class simple_recv : public proton::messaging_handler {
}

if (expected == 0 || received < expected) {
std::cout << msg.body() << std::endl;
std::cout << "MessageID: " << msg.id() << " Body: " << msg.body() << std::endl;
received++;

if (received == expected) {
Expand Down
130 changes: 130 additions & 0 deletions cpp/examples/tx_recv.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/

#include "options.hpp"

#include <proton/connection.hpp>
#include <proton/container.hpp>
#include <proton/message.hpp>
#include <proton/message_id.hpp>
#include <proton/messaging_handler.hpp>
#include <proton/types.hpp>
#include <proton/transaction.hpp>

#include <iostream>
#include <map>
#include <string>

#include <chrono>
#include <thread>

class tx_recv : public proton::messaging_handler, proton::transaction_handler {
private:
proton::receiver receiver;
std::string url;
int expected;
int batch_size;
int current_batch = 0;
int committed = 0;

proton::container *container;
proton::transaction transaction;
proton::connection connection;
public:
tx_recv(const std::string &s, int c, int b):
url(s), expected(c), batch_size(b) {}

void on_container_start(proton::container &c) override {
container = &c;
receiver = c.open_receiver(url);
connection = receiver.connection();
std::cout << " [on_container_start] declare_txn started..." << std::endl;
c.declare_transaction(connection, *this);
std::cout << " [on_container_start] completed!!" << &transaction
<< std::endl;
}

void on_transaction_declare_failed(proton::transaction) {}
void on_transaction_commit_failed(proton::transaction) {
std::cout << "Transaction Commit Failed" << std::endl;
connection.close();
exit(-1);
}

void on_transaction_declared(proton::transaction t) override {
std::cout << "[on_transaction_declared] txn called " << (&t)
<< std::endl;
// connection.close();
std::cout << "[on_transaction_declared] txn is_empty " << (t.is_empty())
<< "\t" << transaction.is_empty() << std::endl;
receiver.add_credit(batch_size);
transaction = t;
}

void on_message(proton::delivery &d, proton::message &msg) override {
std::cout<<"# MESSAGE: " << msg.id() <<": " << msg.body() << std::endl;
transaction.accept(d);
current_batch += 1;
if(current_batch == batch_size) {
transaction = proton::transaction(); // null
}
}

void on_transaction_committed(proton::transaction t) override {
committed += current_batch;
current_batch = 0;
std::cout<<" [OnTxnCommitted] Committed:"<< committed<< std::endl;
if(committed == expected) {
std::cout << "All messages committed" << std::endl;
connection.close();
}
else {
container->declare_transaction(connection, *this);
}
}

};

int main(int argc, char **argv) {
std::string address("127.0.0.1:5672/examples");
int message_count = 9;
int batch_size = 3;
example::options opts(argc, argv);

opts.add_value(address, 'a', "address", "connect and send to URL", "URL");
opts.add_value(message_count, 'm', "messages", "number of messages to send", "COUNT");
opts.add_value(batch_size, 'b', "batch_size", "number of messages in each transaction", "BATCH_SIZE");

try {
opts.parse();

tx_recv recv(address, message_count, batch_size);
proton::container(recv).run();

return 0;
} catch (const example::bad_option& e) {
std::cout << opts << std::endl << e.what() << std::endl;
} catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}

return 1;
}
11 changes: 4 additions & 7 deletions cpp/examples/tx_send.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,14 @@ class tx_send : public proton::messaging_handler, proton::transaction_handler {
int confirmed = 0;

proton::container *container;
// proton::transaction_handler transaction_handler;
proton::transaction transaction;
proton::connection connection;
public:
tx_send(const std::string &s, int c, int b):
url(s), total(c), batch_size(b), sent(0) {}

void on_container_start(proton::container &c) override {
container = &c; // TODO: Fix error
container = &c;
sender = c.open_sender(url);
connection = sender.connection();
std::cout << " [on_container_start] declare_txn started..." << std::endl;
Expand All @@ -76,7 +75,6 @@ class tx_send : public proton::messaging_handler, proton::transaction_handler {
void on_transaction_declared(proton::transaction t) override {
std::cout << "[on_transaction_declared] txn called " << (&t)
<< std::endl;
// connection.close();
std::cout << "[on_transaction_declared] txn is_empty " << (t.is_empty())
<< "\t" << transaction.is_empty() << std::endl;
transaction = t;
Expand All @@ -85,23 +83,22 @@ class tx_send : public proton::messaging_handler, proton::transaction_handler {
}

void on_sendable(proton::sender &s) override {
// send();
std::cout << " [OnSendable] transaction: " << &transaction
<< std::endl;
send(s);
}

void send(proton::sender &s) {
// TODO: Add more condition in while loop
static int unique_id = 10000;
while (!transaction.is_empty() && sender.credit() &&
(committed + current_batch) < total) {
proton::message msg;
std::map<std::string, int> m;
m["sequence"] = committed + current_batch;

msg.id(committed + current_batch + 1);
msg.id(unique_id++);
msg.body(m);
std::cout << " [example] transaction send msg: " << msg
std::cout << "##### [example] transaction send msg: " << msg
<< std::endl;
transaction.send(sender, msg);
current_batch += 1;
Expand Down
3 changes: 2 additions & 1 deletion cpp/include/proton/transaction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class transaction_impl {

void discharge(bool failed);
void release_pending();
void accept(tracker &d);
void accept(delivery &d);
void update(tracker &d, uint64_t state);
void set_id(binary _id);

Expand Down Expand Up @@ -92,6 +92,7 @@ PN_CPP_CLASS_EXTERN transaction {
PN_CPP_EXTERN void declare();
PN_CPP_EXTERN void handle_outcome(proton::tracker);
PN_CPP_EXTERN proton::tracker send(proton::sender s, proton::message msg);
PN_CPP_EXTERN void accept(delivery &t);

friend class transaction_impl;
friend class container::impl;
Expand Down
36 changes: 1 addition & 35 deletions cpp/src/messaging_adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,42 +333,8 @@ void on_link_remote_open(messaging_handler& handler, pn_event_t* event) {
return;
}
std::cout<<" IN on_link_remote_open(.PN_COORDINATOR) success " << std::endl;
std::cout<<" IN on_link_remote_open(.PN_COORDINATOR) have handler " << &handler << std::endl;

// WHY???
// pn_terminus_copy(pn_link_source(lnk), pn_link_remote_source(lnk));
// pn_terminus_copy(pn_link_target(lnk), pn_link_remote_target(lnk));

// We need a new class?
// auto coordinator = pn_link_remote_target(lnk);


// proton::target_options to;
// std::vector<symbol> cap = {proton::symbol("amqp:local-transactions")};
// to.capabilities(cap);
// to.type(PN_COORDINATOR);

// proton::receiver_options ro;
// ro.name("txn-ctrl");
// ro.target(to);
// ro.handler(handler);
// receiver r(make_wrapper<receiver>(lnk));

// proton::receiver rcv = r.connection().open_receiver("does not matter", ro);
std::cout<<" IN on_link_remote_open(.PN_COORDINATOR) have handler " << &handler << std::endl;

// handler.on_receiver_open(rcv);
// credit_topup(lnk);

// pn_delivery_t *dlv = pn_event_delivery(event);
// tracker t(make_wrapper<tracker>(dlv));

// // sender s(make_wrapper<sender>(lnk));
// handler.on_tracker_settle(t);
// TODO: find what to do...
// HAHA.. treating coordinator like sender...
// sender s(make_wrapper<sender>(lnk));
// handler.on_sender_open(s);
// pn_link_close(lnk);
return;
}
if (pn_link_state(lnk) & PN_LOCAL_UNINIT) { // Incoming link
Expand Down
15 changes: 8 additions & 7 deletions cpp/src/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,19 @@ transaction::transaction(transaction_impl *impl)
: _impl(impl) {}
// transaction::transaction( transaction_impl* impl): _impl(impl){}
transaction::~transaction() = default;
void transaction::commit() { _impl->commit(); };
void transaction::abort() { _impl->abort(); };
void transaction::declare() { _impl->declare(); };
bool transaction::is_empty() { return _impl == NULL; };
void transaction::commit() { _impl->commit(); }
void transaction::abort() { _impl->abort(); }
void transaction::declare() { _impl->declare(); }
bool transaction::is_empty() { return _impl == NULL; }
void transaction::accept(delivery &t) { return _impl->accept(t); }
proton::tracker transaction::send(proton::sender s, proton::message msg) {
return _impl->send(s, msg);
};
}
void transaction::handle_outcome(proton::tracker t) {
std::cout << " transaction::handle_outcome = NO OP base class "
<< std::endl;
_impl->handle_outcome(t);
};
}

transaction_impl::transaction_impl(proton::sender &_txn_ctrl,
proton::transaction_handler &_handler,
Expand Down Expand Up @@ -142,7 +143,7 @@ proton::tracker transaction_impl::send(proton::sender s, proton::message msg) {
return tracker;
}

void transaction_impl::accept(tracker &t) {
void transaction_impl::accept(delivery &t) {
// TODO: settle-before-discharge
t.settle();
// pending.push_back(d);
Expand Down

0 comments on commit fa9236d

Please sign in to comment.