PROTON-865: Example and cmake cleanup, minor code cleanup. - Optionally enable C++ in top level cmake for examplesb. Still works without a C++ compiler. - Move cpp examples to the /examples dir, renamed for consistent exe naming conventions. - Integrate example build & auto-test with cmake - Improved exception handling - Simplified exception handling. - Removed nascent logging code, logging should be handled centrally in C library.
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/8074793b Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/8074793b Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/8074793b Branch: refs/heads/cjansen-cpp-client Commit: 8074793b84a6402b01f3639e8cf8fed6b5ba54cc Parents: d56c5d7 Author: Alan Conway <[email protected]> Authored: Mon Jun 1 18:03:36 2015 -0400 Committer: Alan Conway <[email protected]> Committed: Wed Jun 3 11:43:31 2015 -0400 ---------------------------------------------------------------------- CMakeLists.txt | 8 +- examples/CMakeLists.txt | 3 + examples/cpp/CMakeLists.txt | 32 +++ examples/cpp/README.md | 43 +++ examples/cpp/broker.cpp | 201 +++++++++++++ examples/cpp/example_test.py | 105 +++++++ examples/cpp/helloworld.cpp | 69 +++++ examples/cpp/helloworld_blocking.cpp | 70 +++++ examples/cpp/helloworld_direct.cpp | 76 +++++ examples/cpp/simple_recv.cpp | 115 ++++++++ examples/cpp/simple_send.cpp | 122 ++++++++ examples/go/CMakeLists.txt | 29 ++ examples/go/example_test.go | 284 +++++++++++++++++++ proton-c/CMakeLists.txt | 3 - proton-c/bindings/CMakeLists.txt | 8 +- proton-c/bindings/cpp/CMakeLists.txt | 26 -- proton-c/bindings/cpp/README.md | 24 ++ proton-c/bindings/cpp/examples/Broker.cpp | 193 ------------- proton-c/bindings/cpp/examples/HelloWorld.cpp | 62 ---- .../cpp/examples/HelloWorldBlocking.cpp | 65 ----- .../bindings/cpp/examples/HelloWorldDirect.cpp | 70 ----- proton-c/bindings/cpp/examples/SimpleRecv.cpp | 109 ------- proton-c/bindings/cpp/examples/SimpleSend.cpp | 117 -------- .../bindings/cpp/include/proton/cpp/Delivery.h | 2 - .../bindings/cpp/include/proton/cpp/Handle.h | 1 + .../cpp/include/proton/cpp/exceptions.h | 17 +- proton-c/bindings/cpp/src/Connector.cpp | 7 +- proton-c/bindings/cpp/src/Container.cpp | 1 - proton-c/bindings/cpp/src/ContainerImpl.cpp | 2 +- proton-c/bindings/cpp/src/Delivery.cpp | 1 + proton-c/bindings/cpp/src/LogInternal.h | 51 ---- proton-c/bindings/cpp/src/Logger.cpp | 56 ---- proton-c/bindings/cpp/src/exceptions.cpp | 33 --- 33 files changed, 1190 insertions(+), 815 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/CMakeLists.txt b/CMakeLists.txt index 2df2dfb..261fdc0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,16 +20,15 @@ cmake_minimum_required (VERSION 2.6) project (Proton C) +# Enable C++ now for examples and bindings subdirectories, but make it optional. +enable_language(CXX OPTIONAL) + if (MSVC) # No C99 capability, use C++ set(DEFAULT_BUILD_WITH_CXX ON) endif (MSVC) option(BUILD_WITH_CXX "Compile Proton using C++" ${DEFAULT_BUILD_WITH_CXX}) -if (BUILD_WITH_CXX) - project (Proton C CXX) -endif (BUILD_WITH_CXX) - if (CMAKE_CONFIGURATION_TYPES) # There is no single "build type"... message(STATUS "Build types are ${CMAKE_CONFIGURATION_TYPES}") @@ -141,6 +140,7 @@ if (BUILD_JAVA) endif() add_subdirectory(proton-c) +add_subdirectory(examples) install (FILES LICENSE README.md TODO DESTINATION ${PROTON_SHARE}) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/examples/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index feac758..5724e59 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -21,3 +21,6 @@ set (Proton_DIR ${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) add_subdirectory(c/messenger) +if (BUILD_CPP) + add_subdirectory(cpp) +endif() http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/examples/cpp/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/examples/cpp/CMakeLists.txt b/examples/cpp/CMakeLists.txt new file mode 100644 index 0000000..2ce548b --- /dev/null +++ b/examples/cpp/CMakeLists.txt @@ -0,0 +1,32 @@ +# +# 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_directories ("${CMAKE_SOURCE_DIR}/proton-c/bindings/cpp/include") + +foreach(example broker helloworld helloworld_blocking helloworld_direct simple_recv simple_send) + add_executable(${example} ${example}.cpp) + target_link_libraries(${example} qpid-proton-cpp) +endforeach() + +add_test( + NAME cpp_example_test + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/example_test.py -v + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + + http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/examples/cpp/README.md ---------------------------------------------------------------------- diff --git a/examples/cpp/README.md b/examples/cpp/README.md new file mode 100644 index 0000000..2aaf2ef --- /dev/null +++ b/examples/cpp/README.md @@ -0,0 +1,43 @@ +# C++ examples + +## broker.cpp + +A very simple "mini broker". You can use this to run other examples that reqiure +an intermediary, or you can use a real AMQP 1.0 broker. It creates queues +automatically when a client tries to send to or subscribe from a node. + +## helloworld.cpp + +Basic example that connects to an intermediary on localhost:5672, +establishes a subscription from the 'examples' node on that +intermediary, then creates a sending link to the same node and sends +one message. On receving the message back via the subcription, the +connection is closed. + +## helloworld_blocking.cpp + +The same as the basic helloworld.cpp, but using a +synchronous/sequential style wrapper on top of the +asynchronous/reactive API. The purpose of this example is just to show +how different functionality can be easily layered should it be +desired. + +## helloworld_direct.cpp + +A variant of the basic helloworld example, that does not use an +intermediary, but listens for incoming connections itself. It +establishes a connection to itself with a link over which a single +message is sent. This demonstrates the ease with which a simple daemon +can be built using the API. + +## simple_send.cpp + +An example of sending a fixed number of messages and tracking their +(asynchronous) acknowledgement. Messages are sent through the 'examples' node on +an intermediary accessible on port 5672 on localhost. + +# simple_recv.cpp + +Subscribes to the 'examples' node on an intermediary accessible on port 5672 on +localhost. Simply prints out the body of received messages. + http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/examples/cpp/broker.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/broker.cpp b/examples/cpp/broker.cpp new file mode 100644 index 0000000..01160a7 --- /dev/null +++ b/examples/cpp/broker.cpp @@ -0,0 +1,201 @@ +/* + * + * 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 "proton/cpp/Container.h" +#include "proton/cpp/MessagingHandler.h" + +#include <iostream> +#include <deque> +#include <map> +#include <list> +#include <stdlib.h> +#include <string.h> + +using namespace proton::reactor; + +std::string generateUuid(){ + throw "TODO: platform neutral uuid"; +} + +class Queue { + public: + bool dynamic; + typedef std::deque<Message> MsgQ; + typedef std::list<Sender> List; + MsgQ queue; + List consumers; + + Queue(bool dyn = false) : dynamic(dyn), queue(MsgQ()), consumers(List()) {} + + void subscribe(Sender &c) { + consumers.push_back(c); + } + + bool unsubscribe(Sender &c) { + consumers.remove(c); + return (consumers.size() == 0 && (dynamic || queue.size() == 0)); + } + + void publish(Message &m) { + queue.push_back(m); + dispatch(0); + } + + void dispatch(Sender *s) { + while (deliverTo(s)) { + } + } + + bool deliverTo(Sender *consumer) { + // deliver to single consumer if supplied, else all consumers + int count = consumer ? 1 : consumers.size(); + if (!count) return false; + bool result = false; + List::iterator it = consumers.begin(); + if (!consumer && count) consumer = &*it; + + while (queue.size()) { + if (consumer->getCredit()) { + consumer->send(queue.front()); + queue.pop_front(); + result = true; + } + if (--count) + it++; + else + return result; + } + return false; + } +}; + +class Broker : public MessagingHandler { + private: + std::string url; + typedef std::map<std::string, Queue *> QMap; + QMap queues; + public: + + Broker(const std::string &s) : url(s), queues(QMap()) {} + + void onStart(Event &e) { + e.getContainer().listen(url); + std::cout << "broker listening on " << url << std::endl; + } + + Queue &queue(std::string &address) { + QMap::iterator it = queues.find(address); + if (it == queues.end()) { + queues[address] = new Queue(); + return *queues[address]; + } + else { + return *it->second; + } + } + + void onLinkOpening(Event &e) { + Link lnk = e.getLink(); + if (lnk.isSender()) { + Sender sender(lnk); + Terminus remoteSource(lnk.getRemoteSource()); + if (remoteSource.isDynamic()) { + std::string address = generateUuid(); + lnk.getSource().setAddress(address); + Queue *q = new Queue(true); + queues[address] = q; + q->subscribe(sender); + } + else { + std::string address = remoteSource.getAddress(); + if (!address.empty()) { + lnk.getSource().setAddress(address); + queue(address).subscribe(sender); + } + } + } + else { + std::string address = lnk.getRemoteTarget().getAddress(); + if (!address.empty()) + lnk.getTarget().setAddress(address); + } + } + + void unsubscribe (Sender &lnk) { + std::string address = lnk.getSource().getAddress(); + QMap::iterator it = queues.find(address); + if (it != queues.end() && it->second->unsubscribe(lnk)) { + delete it->second; + queues.erase(it); + } + } + + void onLinkClosing(Event &e) { + Link lnk = e.getLink(); + if (lnk.isSender()) { + Sender s(lnk); + unsubscribe(s); + } + } + + void onConnectionClosing(Event &e) { + removeStaleConsumers(e.getConnection()); + } + + void onDisconnected(Event &e) { + removeStaleConsumers(e.getConnection()); + } + + void removeStaleConsumers(Connection &connection) { + Link l = connection.getLinkHead(Endpoint::REMOTE_ACTIVE); + while (l) { + if (l.isSender()) { + Sender s(l); + unsubscribe(s); + } + l = l.getNext(Endpoint::REMOTE_ACTIVE); + } + } + + void onSendable(Event &e) { + Link lnk = e.getLink(); + Sender sender(lnk); + std::string addr = lnk.getSource().getAddress(); + queue(addr).dispatch(&sender); + } + + void onMessage(Event &e) { + std::string addr = e.getLink().getTarget().getAddress(); + Message msg = e.getMessage(); + queue(addr).publish(msg); + } +}; + +int main(int argc, char **argv) { + std::string url = argc > 1 ? argv[1] : ":5672"; + Broker broker(url); + try { + Container(broker).run(); + } catch (const std::exception& e) { + std::cerr << e.what() << std::endl; + return 1; + } +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/examples/cpp/example_test.py ---------------------------------------------------------------------- diff --git a/examples/cpp/example_test.py b/examples/cpp/example_test.py new file mode 100644 index 0000000..9a8ac67 --- /dev/null +++ b/examples/cpp/example_test.py @@ -0,0 +1,105 @@ +# +# 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 +# + +import unittest +import os, sys, socket, time +from random import randrange +from subprocess import Popen, check_output, PIPE + +NULL = open(os.devnull, 'w') + +class Broker(object): + """Run the test broker""" + + @classmethod + def get(cls): + if not hasattr(cls, "_broker"): + cls._broker = Broker() + return cls._broker + + @classmethod + def stop(cls): + if cls._broker and cls._broker.process: + cls._broker.process.kill() + cls._broker = None + + def __init__(self): + self.port = randrange(10000, 20000) + self.addr = ":%s" % self.port + self.process = Popen(["./broker", self.addr], stdout=NULL, stderr=NULL) + # Wait 10 secs for broker to listen + deadline = time.time() + 10 + c = None + while time.time() < deadline: + try: + c = socket.create_connection(("127.0.0.1", self.port), deadline - time.time()) + break + except socket.error as e: + time.sleep(0.01) + if c is None: + raise Exception("Timed out waiting for broker") + c.close() + + +class ExampleTest(unittest.TestCase): + """Test examples""" + + @classmethod + def tearDownClass(self): + Broker.stop() + + def test_helloworld(self): + b = Broker.get() + hw = check_output(["./helloworld", b.addr]) + self.assertEqual("Hello World!\n", hw) + + def test_helloworld_blocking(self): + b = Broker.get() + hw = check_output(["./helloworld_blocking", b.addr]) + self.assertEqual("Hello World!\n", hw) + + def test_helloworld_direct(self): + url = ":%s/examples" % randrange(10000, 20000) + hw = check_output(["./helloworld_direct", url]) + self.assertEqual("Hello World!\n", hw) + + def test_simple_send_recv(self): + b = Broker.get() + n = 5 + send = check_output(["./simple_send", "-a", b.addr, "-m", str(n)]) + self.assertEqual("all messages confirmed\n", send) + recv = check_output(["./simple_recv", "-a", b.addr, "-m", str(n)]) + recv_expect = "simple_recv listening on %s\n" % (b.addr) + recv_expect += "".join(['[%d]: b"some arbitrary binary data"\n' % (i+1) for i in range(n)]) + self.assertEqual(recv_expect, recv) + + def FIXME_test_simple_recv_send(self): + """Start receiver first, then run sender""" + b = Broker.get() + n = 5 + recv = Popen(["./simple_recv", "-a", b.addr, "-m", str(n)], stdout=PIPE) + self.assertEqual("simple_recv listening on %s\n" % (b.addr), recv.stdout.readline()) + send = check_output(["./simple_send", "-a", b.addr, "-m", str(n)]) + self.assertEqual("all messages confirmed\n", send) + recv_expect = "".join(['[%d]: b"some arbitrary binary data"\n' % (i+1) for i in range(n)]) + out, err = recv.communicate() + self.assertEqual(recv_expect, out) + +if __name__ == "__main__": + unittest.main() http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/examples/cpp/helloworld.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/helloworld.cpp b/examples/cpp/helloworld.cpp new file mode 100644 index 0000000..6b58eb7 --- /dev/null +++ b/examples/cpp/helloworld.cpp @@ -0,0 +1,69 @@ +/* + * + * 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 "proton/cpp/Container.h" +#include "proton/cpp/MessagingHandler.h" + +#include <iostream> + + +using namespace proton::reactor; + +class HelloWorld : public MessagingHandler { + private: + std::string server; + std::string address; + public: + + HelloWorld(const std::string &s, const std::string &addr) : server(s), address(addr) {} + + void onStart(Event &e) { + Connection conn = e.getContainer().connect(server); + e.getContainer().createReceiver(conn, address); + e.getContainer().createSender(conn, address); + } + + void onSendable(Event &e) { + Message m; + m.setBody("Hello World!"); + e.getSender().send(m); + e.getSender().close(); + } + + void onMessage(Event &e) { + std::string body = e.getMessage().getBody(); + std::cout << body << std::endl; + e.getConnection().close(); + } + +}; + +int main(int argc, char **argv) { + try { + std::string server = argc > 1 ? argv[1] : ":5672"; + std::string addr = argc > 2 ? argv[2] : "examples"; + HelloWorld hw(server, addr); + Container(hw).run(); + } catch (const std::exception& e) { + std::cerr << e.what() << std::endl; + return 1; + } +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/examples/cpp/helloworld_blocking.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/helloworld_blocking.cpp b/examples/cpp/helloworld_blocking.cpp new file mode 100644 index 0000000..5f443b6 --- /dev/null +++ b/examples/cpp/helloworld_blocking.cpp @@ -0,0 +1,70 @@ +/* + * + * 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 "proton/cpp/Container.h" +#include "proton/cpp/MessagingHandler.h" +#include "proton/cpp/BlockingSender.h" + +#include <iostream> + + +using namespace proton::reactor; + +class HelloWorldBlocking : public MessagingHandler { + private: + std::string server; + std::string address; + public: + + HelloWorldBlocking(const std::string &s, const std::string &addr) : server(s), address(addr) {} + + void onStart(Event &e) { + Connection conn = e.getContainer().connect(server); + e.getContainer().createReceiver(conn, address); + } + + void onMessage(Event &e) { + std::string body = e.getMessage().getBody(); + std::cout << body << std::endl; + e.getConnection().close(); + } + +}; + +int main(int argc, char **argv) { + try { + std::string server = argc > 1 ? argv[1] : ":5672"; + std::string addr = argc > 2 ? argv[2] : "examples"; + BlockingConnection conn = BlockingConnection(server); + BlockingSender sender = conn.createSender(addr); + Message m; + m.setBody("Hello World!"); + sender.send(m); + conn.close(); + + // TODO Temporary hack until blocking receiver available + HelloWorldBlocking hw(server, addr); + Container(hw).run(); + } catch (const std::exception& e) { + std::cerr << e.what() << std::endl; + return 1; + } +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/examples/cpp/helloworld_direct.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/helloworld_direct.cpp b/examples/cpp/helloworld_direct.cpp new file mode 100644 index 0000000..12617cd --- /dev/null +++ b/examples/cpp/helloworld_direct.cpp @@ -0,0 +1,76 @@ +/* + * + * 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 "proton/cpp/MessagingHandler.h" +#include "proton/cpp/Container.h" + +//#include "proton/cpp/Acceptor.h" +#include <iostream> + + +using namespace proton::reactor; + + +class HelloWorldDirect : public MessagingHandler { + private: + std::string url; + Acceptor acceptor; + public: + + HelloWorldDirect(const std::string &u) : url(u) {} + + void onStart(Event &e) { + acceptor = e.getContainer().listen(url); + e.getContainer().createSender(url); + } + + void onSendable(Event &e) { + Message m; + m.setBody("Hello World!"); + e.getSender().send(m); + e.getSender().close(); + } + + void onMessage(Event &e) { + std::string body = e.getMessage().getBody(); + std::cout << body << std::endl; + } + + void onAccepted(Event &e) { + e.getConnection().close(); + } + + void onConnectionClosed(Event &e) { + acceptor.close(); + } + +}; + +int main(int argc, char **argv) { + try { + std::string url = argc > 1 ? argv[1] : ":8888/examples"; + HelloWorldDirect hwd(url); + Container(hwd).run(); + } catch (const std::exception& e) { + std::cerr << e.what() << std::endl; + return 1; + } +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/examples/cpp/simple_recv.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/simple_recv.cpp b/examples/cpp/simple_recv.cpp new file mode 100644 index 0000000..42c561b --- /dev/null +++ b/examples/cpp/simple_recv.cpp @@ -0,0 +1,115 @@ +/* + * + * 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 "proton/cpp/Container.h" +#include "proton/cpp/MessagingHandler.h" +#include "proton/cpp/Link.h" + +#include <iostream> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + + +using namespace proton::reactor; + +class Recv : public MessagingHandler { + private: + std::string url; + int expected; + int received; + public: + + Recv(const std::string &s, int c) : url(s), expected(c), received(0) {} + + void onStart(Event &e) { + e.getContainer().createReceiver(url); + std::cout << "simple_recv listening on " << url << std::endl; + } + + void onMessage(Event &e) { + uint64_t id = 0; + Message msg = e.getMessage(); + if (msg.getIdType() == PN_ULONG) { + id = msg.getId(); + if (id < received) + return; // ignore duplicate + } + if (expected == 0 || received < expected) { + std::cout << '[' << id << "]: " << msg.getBody() << std::endl; + received++; + if (received == expected) { + e.getReceiver().close(); + e.getConnection().close(); + } + } + } +}; + +static void parse_options(int argc, char **argv, int &count, std::string &addr); + +int main(int argc, char **argv) { + try { + int messageCount = 100; + std::string address("localhost:5672/examples"); + parse_options(argc, argv, messageCount, address); + Recv recv(address, messageCount); + Container(recv).run(); + } catch (const std::exception& e) { + std::cerr << e.what() << std::endl; + return 1; + } +} + + +static void usage() { + std::cout << "Usage: simple_recv -m message_count -a address:" << std::endl; + exit (1); +} + + +static void parse_options(int argc, char **argv, int &count, std::string &addr) { + int c, i; + for (i = 1; i < argc; i++) { + if (strlen(argv[i]) == 2 && argv[i][0] == '-') { + c = argv[i][1]; + const char *nextarg = i < argc ? argv[i+1] : NULL; + + switch (c) { + case 'a': + if (!nextarg) usage(); + addr = nextarg; + i++; + break; + case 'm': + if (!nextarg) usage(); + unsigned newc; + if (sscanf( nextarg, "%d", &newc) != 1) usage(); + count = newc; + i++; + break; + default: + usage(); + } + } + else usage(); + } +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/examples/cpp/simple_send.cpp ---------------------------------------------------------------------- diff --git a/examples/cpp/simple_send.cpp b/examples/cpp/simple_send.cpp new file mode 100644 index 0000000..eb87c8a --- /dev/null +++ b/examples/cpp/simple_send.cpp @@ -0,0 +1,122 @@ +/* + * + * 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 "proton/cpp/Container.h" +#include "proton/cpp/MessagingHandler.h" +#include "proton/cpp/Connection.h" + +#include <iostream> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + + +using namespace proton::reactor; + +class Send : public MessagingHandler { + private: + std::string url; + int sent; + int confirmed; + int total; + public: + + Send(const std::string &s, int c) : url(s), sent(0), confirmed(0), total(c) {} + + void onStart(Event &e) { + e.getContainer().createSender(url); + } + + void onSendable(Event &e) { + Sender sender = e.getSender(); + while (sender.getCredit() && sent < total) { + Message msg; + msg.setId(sent + 1); + // TODO: fancy map body content as in Python example. Simple binary for now. + const char *bin = "some arbitrary binary data"; + msg.setBody(bin, strlen(bin)); + sender.send(msg); + sent++; + } + } + + void onAccepted(Event &e) { + confirmed++; + if (confirmed == total) { + std::cout << "all messages confirmed" << std::endl; + e.getConnection().close(); + } + } + + void onDisconnected(Event &e) { + sent = confirmed; + } +}; + +static void parse_options(int argc, char **argv, int &count, std::string &addr); + +int main(int argc, char **argv) { + try { + int messageCount = 100; + std::string address("localhost:5672/examples"); + parse_options(argc, argv, messageCount, address); + Send send(address, messageCount); + Container(send).run(); + } catch (const std::exception& e) { + std::cerr << e.what() << std::endl; + return 1; + } +} + + +static void usage() { + std::cout << "Usage: simple_send -m message_count -a address:" << std::endl; + exit (1); +} + + +static void parse_options(int argc, char **argv, int &count, std::string &addr) { + int c, i; + for (i = 1; i < argc; i++) { + if (strlen(argv[i]) == 2 && argv[i][0] == '-') { + c = argv[i][1]; + const char *nextarg = i < argc ? argv[i+1] : NULL; + + switch (c) { + case 'a': + if (!nextarg) usage(); + addr = nextarg; + i++; + break; + case 'm': + if (!nextarg) usage(); + unsigned newc; + if (sscanf( nextarg, "%d", &newc) != 1) usage(); + count = newc; + i++; + break; + default: + usage(); + } + } + else usage(); + } +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/examples/go/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/examples/go/CMakeLists.txt b/examples/go/CMakeLists.txt new file mode 100644 index 0000000..464ed7c --- /dev/null +++ b/examples/go/CMakeLists.txt @@ -0,0 +1,29 @@ +# +# 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. +# + +# FIXME aconway 2015-05-20: +# - use proton build for Go includes & libs. +# - pre-build go libraries? Respect user GOPATH? + +if(BUILD_GO) + add_test( + NAME go_example_test + COMMAND ${GO_TEST} example_test.go -rpath ${CMAKE_BINARY_DIR}/proton-c + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) +endif() http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/examples/go/example_test.go ---------------------------------------------------------------------- diff --git a/examples/go/example_test.go b/examples/go/example_test.go new file mode 100644 index 0000000..8879c38 --- /dev/null +++ b/examples/go/example_test.go @@ -0,0 +1,284 @@ +/* +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. +*/ + +// Tests to verify that example code behaves as expected. +// Run in this directory with `go test example_test.go` +// +package main + +import ( + "bufio" + "bytes" + "flag" + "fmt" + "io" + "io/ioutil" + "math/rand" + "net" + "os" + "os/exec" + "path" + "path/filepath" + "reflect" + "testing" + "time" +) + +func panicIf(err error) { + if err != nil { + panic(err) + } +} + +// A demo broker process +type broker struct { + cmd *exec.Cmd + addr string + runerr chan error + err error +} + +// Try to connect to the broker to verify it is ready, give up after a timeout +func (b *broker) check() error { + dialer := net.Dialer{Deadline: time.Now().Add(time.Second * 10)} + for { + c, err := dialer.Dial("tcp", b.addr) + if err == nil { // Success + c.Close() + return nil + } + select { + case runerr := <-b.runerr: // Broker exited. + return runerr + default: + } + if neterr, ok := err.(net.Error); ok && neterr.Timeout() { // Running but timed out + b.stop() + return fmt.Errorf("timed out waiting for broker") + } + time.Sleep(time.Second / 10) + } +} + +// Start the demo broker, wait till it is listening on *addr. No-op if already started. +func (b *broker) start() error { + if b.cmd == nil { // Not already started + // FIXME aconway 2015-04-30: better way to pick/configure a broker port. + b.addr = fmt.Sprintf("127.0.0.1:%d", rand.Intn(10000)+10000) + b.cmd = exampleCommand("event_broker", "-addr", b.addr) + b.runerr = make(chan error) + b.cmd.Stderr, b.cmd.Stdout = os.Stderr, os.Stdout + go func() { + b.runerr <- b.cmd.Run() + }() + b.err = b.check() + } + return b.err +} + +func (b *broker) stop() { + if b != nil && b.cmd != nil { + b.cmd.Process.Kill() + b.cmd.Wait() + } +} + +func checkEqual(want interface{}, got interface{}) error { + if reflect.DeepEqual(want, got) { + return nil + } + return fmt.Errorf("%#v != %#v", want, got) +} + +// runCommand returns an exec.Cmd to run an example. +func exampleCommand(prog string, arg ...string) *exec.Cmd { + build(prog + ".go") + args := []string{} + if *debug { + args = append(args, "-debug=true") + } + args = append(args, arg...) + cmd := exec.Command(exepath(prog), args...) + cmd.Stderr = os.Stderr + return cmd +} + +// Run an example Go program, return the combined output as a string. +func runExample(prog string, arg ...string) (string, error) { + cmd := exampleCommand(prog, arg...) + out, err := cmd.Output() + return string(out), err +} + +func prefix(prefix string, err error) error { + if err != nil { + return fmt.Errorf("%s: %s", prefix, err) + } + return nil +} + +func runExampleWant(want string, prog string, args ...string) error { + out, err := runExample(prog, args...) + if err != nil { + return fmt.Errorf("%s failed: %s: %s", prog, err, out) + } + return prefix(prog, checkEqual(want, out)) +} + +func exampleArgs(args ...string) []string { + return append(args, testBroker.addr+"/foo", testBroker.addr+"/bar", testBroker.addr+"/baz") +} + +// Send then receive +func TestExampleSendReceive(t *testing.T) { + if testing.Short() { + t.Skip("Skip demo tests in short mode") + } + testBroker.start() + err := runExampleWant( + "Received all 15 acknowledgements\n", + "send", + exampleArgs("-count", "5")...) + if err != nil { + t.Fatal(err) + } + err = runExampleWant( + "Listening on 3 connections\nReceived 15 messages\n", + "receive", + exampleArgs("-count", "15")...) + if err != nil { + t.Fatal(err) + } +} + +var ready error + +func init() { ready = fmt.Errorf("Ready") } + +// Run receive in a goroutine. +// Send ready on errchan when it is listening. +// Send final error when it is done. +// Returns the Cmd, caller must Wait() +func goReceiveWant(errchan chan<- error, want string, arg ...string) *exec.Cmd { + cmd := exampleCommand("receive", arg...) + go func() { + pipe, err := cmd.StdoutPipe() + if err != nil { + errchan <- err + return + } + out := bufio.NewReader(pipe) + cmd.Start() + line, err := out.ReadString('\n') + if err != nil && err != io.EOF { + errchan <- err + return + } + listening := "Listening on 3 connections\n" + if line != listening { + errchan <- checkEqual(listening, line) + return + } + errchan <- ready + buf := bytes.Buffer{} + io.Copy(&buf, out) // Collect the rest of the output + errchan <- checkEqual(want, buf.String()) + close(errchan) + }() + return cmd +} + +// Start receiver first, wait till it is running, then send. +func TestExampleReceiveSend(t *testing.T) { + if testing.Short() { + t.Skip("Skip demo tests in short mode") + } + testBroker.start() + recvErr := make(chan error) + recvCmd := goReceiveWant(recvErr, + "Received 15 messages\n", + exampleArgs("-count", "15")...) + defer func() { + recvCmd.Process.Kill() + recvCmd.Wait() + }() + if err := <-recvErr; err != ready { // Wait for receiver ready + t.Fatal(err) + } + err := runExampleWant( + "Received all 15 acknowledgements\n", + "send", + exampleArgs("-count", "5")...) + if err != nil { + t.Fatal(err) + } + if err := <-recvErr; err != nil { + t.Fatal(err) + } +} + +func exepath(relative string) string { + if binDir == "" { + panic("bindir not set, cannot run example binaries") + } + return path.Join(binDir, relative) +} + +var testBroker *broker +var binDir, exampleDir string +var built map[string]bool + +func init() { + built = make(map[string]bool) +} + +func build(prog string) { + if !built[prog] { + args := []string{"build"} + if *rpath != "" { + args = append(args, "-ldflags", "-r "+*rpath) + } + args = append(args, path.Join(exampleDir, prog)) + build := exec.Command("go", args...) + build.Dir = binDir + out, err := build.CombinedOutput() + if err != nil { + panic(fmt.Errorf("%v: %s", err, out)) + } + built[prog] = true + } +} + +var rpath = flag.String("rpath", "", "Runtime path for test executables") +var debug = flag.Bool("debug", false, "Debugging output from examples") + +func TestMain(m *testing.M) { + rand.Seed(time.Now().UTC().UnixNano()) + var err error + exampleDir, err = filepath.Abs(".") + panicIf(err) + binDir, err = ioutil.TempDir("", "example_test.go") + panicIf(err) + defer os.Remove(binDir) // Clean up binaries + testBroker = &broker{} // Broker is started on-demand by tests. + testBroker.stop() + status := m.Run() + testBroker.stop() + os.Exit(status) +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/proton-c/CMakeLists.txt b/proton-c/CMakeLists.txt index 1347f16..aaf9a82 100644 --- a/proton-c/CMakeLists.txt +++ b/proton-c/CMakeLists.txt @@ -574,6 +574,3 @@ if (BUILD_JAVASCRIPT) add_test (javascript-codec ${env_py} node ${pn_test_root}/javascript/codec.js) add_test (javascript-message ${env_py} node ${pn_test_root}/javascript/message.js) endif (BUILD_JAVASCRIPT) - -# build examples to make sure they still work -add_subdirectory(../examples ../examples) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/proton-c/bindings/CMakeLists.txt b/proton-c/bindings/CMakeLists.txt index f426ef3..e976bc7 100644 --- a/proton-c/bindings/CMakeLists.txt +++ b/proton-c/bindings/CMakeLists.txt @@ -109,10 +109,10 @@ if (EMSCRIPTEN_FOUND) set (DEFAULT_JAVASCRIPT ON) endif (EMSCRIPTEN_FOUND) -# C++ client: very experimental. To try, change this to "ON" -# or provide -DBUILD_CPP=ON to CMake -set (DEFAULT_CPP OFF) - +# Prerequisites for C++ +if (CMAKE_CXX_COMPILER) + set (DEFAULT_CPP ON) +endif (CMAKE_CXX_COMPILER) # Shouldn't need to modify below here when adding new language binding foreach(BINDING ${BINDINGS}) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/CMakeLists.txt b/proton-c/bindings/cpp/CMakeLists.txt index 34123ed..f9e747c 100644 --- a/proton-c/bindings/cpp/CMakeLists.txt +++ b/proton-c/bindings/cpp/CMakeLists.txt @@ -17,8 +17,6 @@ # under the License. # -project (Proton C CXX) - include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/src") include_directories ("${CMAKE_CURRENT_SOURCE_DIR}/include") @@ -53,21 +51,13 @@ set (qpid-proton-cpp-core src/Delivery.cpp src/Acking.cpp src/Transport.cpp - src/Logger.cpp src/contexts.cpp - src/exceptions.cpp src/blocking/BlockingConnection.cpp src/blocking/BlockingConnectionImpl.cpp src/blocking/BlockingLink.cpp src/blocking/BlockingSender.cpp ) -#set_source_files_properties ( -# ${qpid-proton-cpp-core} -# PROPERTIES -# COMPILE_FLAGS "${COMPILE_WARNING_FLAGS} ${COMPILE_LANGUAGE_FLAGS}" -# ) - set_source_files_properties (${qpid-proton-cpp-platform} PROPERTIES LANGUAGE CXX) set_source_files_properties ( ${qpid-proton-cpp-platform} @@ -76,8 +66,6 @@ set_source_files_properties ( COMPILE_DEFINITIONS "${PLATFORM_DEFINITIONS}" ) - - add_library ( qpid-proton-cpp SHARED @@ -97,20 +85,6 @@ set_target_properties ( LINK_FLAGS "${CATCH_UNDEFINED}" ) -add_executable (HelloWorld examples/HelloWorld.cpp) -target_link_libraries (HelloWorld qpid-proton-cpp) -add_executable (HelloWorldDirect examples/HelloWorldDirect.cpp) -target_link_libraries (HelloWorldDirect qpid-proton-cpp) -add_executable (SimpleRecv examples/SimpleRecv.cpp) -target_link_libraries (SimpleRecv qpid-proton-cpp) -add_executable (SimpleSend examples/SimpleSend.cpp) -target_link_libraries (SimpleSend qpid-proton-cpp) -add_executable (Broker examples/Broker.cpp) -target_link_libraries (Broker qpid-proton-cpp) -add_executable (HelloWorldBlocking examples/HelloWorldBlocking.cpp) -target_link_libraries (HelloWorldBlocking qpid-proton-cpp) - - install (TARGETS qpid-proton-cpp EXPORT proton ARCHIVE DESTINATION ${LIB_INSTALL_DIR} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/README.md ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/README.md b/proton-c/bindings/cpp/README.md new file mode 100644 index 0000000..cf16577 --- /dev/null +++ b/proton-c/bindings/cpp/README.md @@ -0,0 +1,24 @@ +# C++ binding for proton. + +This is a C++ wrapper for the proton reactor API. +It is very similar to the python wrapper for the same API. + +There are [examples](../../../examples/cpp/README.md) and the header files have +API documentation in doxygen format. + +# TO DO + +There are a number of things that remain to be done. + +- Type mapping between AMQP and C++ types, e.g. encoding std::map as map message. + +- Finish blocking API & demos. +- API documentation, HTML docs on website. +- FIXME and TODO notes in code, esp. error handling, missing sender/receiver/connection methods. + +- Valgrind for automated tests and demos. +- More automated tests and examples. + +- Security: SASL/SSL support. +- Reconnection + http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/examples/Broker.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/examples/Broker.cpp b/proton-c/bindings/cpp/examples/Broker.cpp deleted file mode 100644 index 7d5214d..0000000 --- a/proton-c/bindings/cpp/examples/Broker.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* - * - * 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 "proton/cpp/Container.h" -#include "proton/cpp/MessagingHandler.h" - -#include <iostream> -#include <deque> -#include <map> -#include <list> - - -using namespace proton::reactor; - -std::string generateUuid(){ - throw "TODO: platform neutral uuid"; -} - -class Queue { - public: - bool dynamic; - typedef std::deque<Message> MsgQ; - typedef std::list<Sender> List; - MsgQ queue; - List consumers; - - Queue(bool dyn = false) : dynamic(dyn), queue(MsgQ()), consumers(List()) {} - - void subscribe(Sender &c) { - consumers.push_back(c); - } - - bool unsubscribe(Sender &c) { - consumers.remove(c); - return (consumers.size() == 0 && (dynamic || queue.size() == 0)); - } - - void publish(Message &m) { - queue.push_back(m); - dispatch(0); - } - - void dispatch(Sender *s) { - while (deliverTo(s)) { - } - } - - bool deliverTo(Sender *consumer) { - // deliver to single consumer if supplied, else all consumers - int count = consumer ? 1 : consumers.size(); - if (!count) return false; - bool result = false; - List::iterator it = consumers.begin(); - if (!consumer && count) consumer = &*it; - - while (queue.size()) { - if (consumer->getCredit()) { - consumer->send(queue.front()); - queue.pop_front(); - result = true; - } - if (--count) - it++; - else - return result; - } - return false; - } -}; - -class Broker : public MessagingHandler { - private: - std::string url; - typedef std::map<std::string, Queue *> QMap; - QMap queues; - public: - - Broker(const std::string &s) : url(s), queues(QMap()) {} - - void onStart(Event &e) { - e.getContainer().listen(url); - } - - Queue &queue(std::string &address) { - QMap::iterator it = queues.find(address); - if (it == queues.end()) { - queues[address] = new Queue(); - return *queues[address]; - } - else { - return *it->second; - } - } - - void onLinkOpening(Event &e) { - Link lnk = e.getLink(); - if (lnk.isSender()) { - Sender sender(lnk); - Terminus remoteSource(lnk.getRemoteSource()); - if (remoteSource.isDynamic()) { - std::string address = generateUuid(); - lnk.getSource().setAddress(address); - Queue *q = new Queue(true); - queues[address] = q; - q->subscribe(sender); - } - else { - std::string address = remoteSource.getAddress(); - if (!address.empty()) { - lnk.getSource().setAddress(address); - queue(address).subscribe(sender); - } - } - } - else { - std::string address = lnk.getRemoteTarget().getAddress(); - if (!address.empty()) - lnk.getTarget().setAddress(address); - } - } - - void unsubscribe (Sender &lnk) { - std::string address = lnk.getSource().getAddress(); - QMap::iterator it = queues.find(address); - if (it != queues.end() && it->second->unsubscribe(lnk)) { - delete it->second; - queues.erase(it); - } - } - - void onLinkClosing(Event &e) { - Link lnk = e.getLink(); - if (lnk.isSender()) { - Sender s(lnk); - unsubscribe(s); - } - } - - void onConnectionClosing(Event &e) { - removeStaleConsumers(e.getConnection()); - } - - void onDisconnected(Event &e) { - removeStaleConsumers(e.getConnection()); - } - - void removeStaleConsumers(Connection &connection) { - Link l = connection.getLinkHead(Endpoint::REMOTE_ACTIVE); - while (l) { - if (l.isSender()) { - Sender s(l); - unsubscribe(s); - } - l = l.getNext(Endpoint::REMOTE_ACTIVE); - } - } - - void onSendable(Event &e) { - Link lnk = e.getLink(); - Sender sender(lnk); - std::string addr = lnk.getSource().getAddress(); - queue(addr).dispatch(&sender); - } - - void onMessage(Event &e) { - std::string addr = e.getLink().getTarget().getAddress(); - Message msg = e.getMessage(); - queue(addr).publish(msg); - } -}; - -int main(int argc, char **argv) { - Broker hw("localhost:5672"); - Container(hw).run(); -} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/examples/HelloWorld.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/examples/HelloWorld.cpp b/proton-c/bindings/cpp/examples/HelloWorld.cpp deleted file mode 100644 index 1fc124b..0000000 --- a/proton-c/bindings/cpp/examples/HelloWorld.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * - * 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 "proton/cpp/Container.h" -#include "proton/cpp/MessagingHandler.h" - -#include <iostream> - - -using namespace proton::reactor; - -class HelloWorld : public MessagingHandler { - private: - std::string server; - std::string address; - public: - - HelloWorld(const std::string &s, const std::string &addr) : server(s), address(addr) {} - - void onStart(Event &e) { - Connection conn = e.getContainer().connect(server); - e.getContainer().createReceiver(conn, address); - e.getContainer().createSender(conn, address); - } - - void onSendable(Event &e) { - Message m; - m.setBody("Hello World!"); - e.getSender().send(m); - e.getSender().close(); - } - - void onMessage(Event &e) { - std::string body = e.getMessage().getBody(); - std::cout << body << std::endl; - e.getConnection().close(); - } - -}; - -int main(int argc, char **argv) { - HelloWorld hw("localhost:5672", "examples"); - Container(hw).run(); -} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/examples/HelloWorldBlocking.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/examples/HelloWorldBlocking.cpp b/proton-c/bindings/cpp/examples/HelloWorldBlocking.cpp deleted file mode 100644 index a3f729c..0000000 --- a/proton-c/bindings/cpp/examples/HelloWorldBlocking.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * - * 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 "proton/cpp/Container.h" -#include "proton/cpp/MessagingHandler.h" -#include "proton/cpp/BlockingSender.h" - -#include <iostream> - - -using namespace proton::reactor; - -class HelloWorldBlocking : public MessagingHandler { - private: - std::string server; - std::string address; - public: - - HelloWorldBlocking(const std::string &s, const std::string &addr) : server(s), address(addr) {} - - void onStart(Event &e) { - Connection conn = e.getContainer().connect(server); - e.getContainer().createReceiver(conn, address); - } - - void onMessage(Event &e) { - std::string body = e.getMessage().getBody(); - std::cout << body << std::endl; - e.getConnection().close(); - } - -}; - -int main(int argc, char **argv) { - std::string url("localhost:5672"); - std::string addr("examples"); - BlockingConnection conn = BlockingConnection(url); - BlockingSender sender = conn.createSender(addr); - Message m; - m.setBody("Hello World!"); - sender.send(m); - conn.close(); - - // Temporary hack until blocking receiver available - HelloWorldBlocking hw("localhost:5672", "examples"); - Container(hw).run(); -} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/examples/HelloWorldDirect.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/examples/HelloWorldDirect.cpp b/proton-c/bindings/cpp/examples/HelloWorldDirect.cpp deleted file mode 100644 index a695dd0..0000000 --- a/proton-c/bindings/cpp/examples/HelloWorldDirect.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * - * 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 "proton/cpp/MessagingHandler.h" -#include "proton/cpp/Container.h" - -//#include "proton/cpp/Acceptor.h" -#include <iostream> - - -using namespace proton::reactor; - - -class HelloWorldDirect : public MessagingHandler { - private: - std::string url; - Acceptor acceptor; - public: - - HelloWorldDirect(const std::string &u) : url(u) {} - - void onStart(Event &e) { - acceptor = e.getContainer().listen(url); - e.getContainer().createSender(url); - } - - void onSendable(Event &e) { - Message m; - m.setBody("Hello World!"); - e.getSender().send(m); - e.getSender().close(); - } - - void onMessage(Event &e) { - std::string body = e.getMessage().getBody(); - std::cout << body << std::endl; - } - - void onAccepted(Event &e) { - e.getConnection().close(); - } - - void onConnectionClosed(Event &e) { - acceptor.close(); - } - -}; - -int main(int argc, char **argv) { - HelloWorldDirect hwd("localhost:8888/examples"); - Container(hwd).run(); -} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/examples/SimpleRecv.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/examples/SimpleRecv.cpp b/proton-c/bindings/cpp/examples/SimpleRecv.cpp deleted file mode 100644 index 22778f0..0000000 --- a/proton-c/bindings/cpp/examples/SimpleRecv.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * - * 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 "proton/cpp/Container.h" -#include "proton/cpp/MessagingHandler.h" -#include "proton/cpp/Link.h" - -#include <iostream> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - - -using namespace proton::reactor; - -class Recv : public MessagingHandler { - private: - std::string url; - int expected; - int received; - public: - - Recv(const std::string &s, int c) : url(s), expected(c), received(0) {} - - void onStart(Event &e) { - e.getContainer().createReceiver(url); - } - - void onMessage(Event &e) { - uint64_t id = 0; - Message msg = e.getMessage(); - if (msg.getIdType() == PN_ULONG) { - id = msg.getId(); - if (id < received) - return; // ignore duplicate - } - if (expected == 0 || received < expected) { - std::cout << '[' << id << "]: " << msg.getBody() << std::endl; - received++; - if (received == expected) { - e.getReceiver().close(); - e.getConnection().close(); - } - } - } -}; - -static void parse_options(int argc, char **argv, int &count, std::string &addr); - -int main(int argc, char **argv) { - int messageCount = 100; - std::string address("localhost:5672/examples"); - parse_options(argc, argv, messageCount, address); - Recv recv(address, messageCount); - Container(recv).run(); -} - - -static void usage() { - std::cout << "Usage: SimpleRecv -m message_count -a address:" << std::endl; - exit (1); -} - - -static void parse_options(int argc, char **argv, int &count, std::string &addr) { - int c, i; - for (i = 1; i < argc; i++) { - if (strlen(argv[i]) == 2 && argv[i][0] == '-') { - c = argv[i][1]; - const char *nextarg = i < argc ? argv[i+1] : NULL; - - switch (c) { - case 'a': - if (!nextarg) usage(); - addr = nextarg; - i++; - break; - case 'm': - if (!nextarg) usage(); - unsigned newc; - if (sscanf( nextarg, "%d", &newc) != 1) usage(); - count = newc; - i++; - break; - default: - usage(); - } - } - else usage(); - } -} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/examples/SimpleSend.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/examples/SimpleSend.cpp b/proton-c/bindings/cpp/examples/SimpleSend.cpp deleted file mode 100644 index 89ca39d..0000000 --- a/proton-c/bindings/cpp/examples/SimpleSend.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * - * 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 "proton/cpp/Container.h" -#include "proton/cpp/MessagingHandler.h" -#include "proton/cpp/Connection.h" - -#include <iostream> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - - -using namespace proton::reactor; - -class Send : public MessagingHandler { - private: - std::string url; - int sent; - int confirmed; - int total; - public: - - Send(const std::string &s, int c) : url(s), sent(0), confirmed(0), total(c) {} - - void onStart(Event &e) { - e.getContainer().createSender(url); - } - - void onSendable(Event &e) { - Sender sender = e.getSender(); - while (sender.getCredit() && sent < total) { - Message msg; - msg.setId(sent + 1); - // TODO: fancy map body content as in Python example. Simple binary for now. - const char *bin = "some arbitrary binary data"; - msg.setBody(bin, strlen(bin)); - sender.send(msg); - sent++; - } - } - - void onAccepted(Event &e) { - confirmed++; - if (confirmed == total) { - std::cout << "all messages confirmed" << std::endl; - e.getConnection().close(); - } - } - - void onDisconnected(Event &e) { - sent = confirmed; - } -}; - -static void parse_options(int argc, char **argv, int &count, std::string &addr); - -int main(int argc, char **argv) { - int messageCount = 100; - std::string address("localhost:5672/examples"); - parse_options(argc, argv, messageCount, address); - Send send(address, messageCount); - Container(send).run(); -} - - -static void usage() { - std::cout << "Usage: SimpleSend -m message_count -a address:" << std::endl; - exit (1); -} - - -static void parse_options(int argc, char **argv, int &count, std::string &addr) { - int c, i; - for (i = 1; i < argc; i++) { - if (strlen(argv[i]) == 2 && argv[i][0] == '-') { - c = argv[i][1]; - const char *nextarg = i < argc ? argv[i+1] : NULL; - - switch (c) { - case 'a': - if (!nextarg) usage(); - addr = nextarg; - i++; - break; - case 'm': - if (!nextarg) usage(); - unsigned newc; - if (sscanf( nextarg, "%d", &newc) != 1) usage(); - count = newc; - i++; - break; - default: - usage(); - } - } - else usage(); - } -} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/include/proton/cpp/Delivery.h ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/cpp/Delivery.h b/proton-c/bindings/cpp/include/proton/cpp/Delivery.h index 8171dd5..089ae1b 100644 --- a/proton-c/bindings/cpp/include/proton/cpp/Delivery.h +++ b/proton-c/bindings/cpp/include/proton/cpp/Delivery.h @@ -24,8 +24,6 @@ #include "proton/cpp/ImportExport.h" #include "proton/cpp/ProtonHandle.h" -#include "ProtonImplRef.h" - #include "proton/delivery.h" #include "proton/disposition.h" http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/include/proton/cpp/Handle.h ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/cpp/Handle.h b/proton-c/bindings/cpp/include/proton/cpp/Handle.h index 77b7814..2cf3f99 100644 --- a/proton-c/bindings/cpp/include/proton/cpp/Handle.h +++ b/proton-c/bindings/cpp/include/proton/cpp/Handle.h @@ -28,6 +28,7 @@ namespace proton { namespace reactor { template <class> class PrivateImplRef; +template <class> class ProtonImplRef; /** * A handle is like a pointer: refers to an underlying implementation object. http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/include/proton/cpp/exceptions.h ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/cpp/exceptions.h b/proton-c/bindings/cpp/include/proton/cpp/exceptions.h index 713c5c5..9fdef94 100644 --- a/proton-c/bindings/cpp/include/proton/cpp/exceptions.h +++ b/proton-c/bindings/cpp/include/proton/cpp/exceptions.h @@ -21,34 +21,27 @@ * under the License. * */ -#include "proton/cpp/ImportExport.h" -#include <string> -#include <exception> +#include <stdexcept> namespace proton { namespace reactor { -class ProtonException : public std::exception +class ProtonException : public std::runtime_error { public: - PROTON_CPP_EXTERN explicit ProtonException(const std::string& message=std::string()) throw(); - PROTON_CPP_EXTERN virtual ~ProtonException() throw(); - PROTON_CPP_EXTERN virtual const char* what() const throw(); - - private: - const std::string message; + explicit ProtonException(const std::string& msg) throw() : std::runtime_error(msg) {} }; class MessageReject : public ProtonException { public: - PROTON_CPP_EXTERN explicit MessageReject(const std::string& message=std::string()) throw(); + explicit MessageReject(const std::string& msg) throw() : ProtonException(msg) {} }; class MessageRelease : public ProtonException { public: - PROTON_CPP_EXTERN explicit MessageRelease(const std::string& message=std::string()) throw(); + explicit MessageRelease(const std::string& msg) throw() : ProtonException(msg) {} }; }} // namespace proton::reactor http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/src/Connector.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/Connector.cpp b/proton-c/bindings/cpp/src/Connector.cpp index 8ebdfb6..fc6eed3 100644 --- a/proton-c/bindings/cpp/src/Connector.cpp +++ b/proton-c/bindings/cpp/src/Connector.cpp @@ -27,7 +27,6 @@ #include "Connector.h" #include "ConnectionImpl.h" #include "Url.h" -#include "LogInternal.h" namespace proton { namespace reactor { @@ -46,7 +45,6 @@ void Connector::connect() { Url url(address); std::string hostname = url.getHost() + ":" + url.getPort(); pn_connection_set_hostname(conn, hostname.c_str()); - PN_CPP_LOG(info, "connecting to " << hostname << "..."); transport = new Transport(); transport->bind(connection); connection.impl->transport = transport; @@ -57,16 +55,13 @@ void Connector::onConnectionLocalOpen(Event &e) { connect(); } -void Connector::onConnectionRemoteOpen(Event &e) { - PN_CPP_LOG(info, "connected to " << e.getConnection().getHostname()); -} +void Connector::onConnectionRemoteOpen(Event &e) {} void Connector::onConnectionInit(Event &e) { } void Connector::onTransportClosed(Event &e) { // TODO: prepend with reconnect logic - PN_CPP_LOG(info, "Disconnected"); pn_connection_release(connection.impl->pnConnection); // No more interaction, so drop our counted reference. connection = Connection(); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/src/Container.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/Container.cpp b/proton-c/bindings/cpp/src/Container.cpp index e72f484..5a551a1 100644 --- a/proton-c/bindings/cpp/src/Container.cpp +++ b/proton-c/bindings/cpp/src/Container.cpp @@ -27,7 +27,6 @@ #include "proton/cpp/exceptions.h" #include "ContainerImpl.h" #include "PrivateImplRef.h" -#include "LogInternal.h" #include "Connector.h" #include "contexts.h" http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/src/ContainerImpl.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/ContainerImpl.cpp b/proton-c/bindings/cpp/src/ContainerImpl.cpp index 1424dbb..ce69928 100644 --- a/proton-c/bindings/cpp/src/ContainerImpl.cpp +++ b/proton-c/bindings/cpp/src/ContainerImpl.cpp @@ -25,8 +25,8 @@ #include "proton/cpp/MessagingAdapter.h" #include "proton/cpp/Acceptor.h" #include "proton/cpp/exceptions.h" -#include "LogInternal.h" +#include "Msg.h" #include "ContainerImpl.h" #include "ConnectionImpl.h" #include "Connector.h" http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/src/Delivery.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/Delivery.cpp b/proton-c/bindings/cpp/src/Delivery.cpp index 990e394..d0b2f3c 100644 --- a/proton-c/bindings/cpp/src/Delivery.cpp +++ b/proton-c/bindings/cpp/src/Delivery.cpp @@ -21,6 +21,7 @@ #include "proton/cpp/Delivery.h" #include "proton/delivery.h" +#include "ProtonImplRef.h" namespace proton { namespace reactor { http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/src/LogInternal.h ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/LogInternal.h b/proton-c/bindings/cpp/src/LogInternal.h deleted file mode 100644 index 427f90b..0000000 --- a/proton-c/bindings/cpp/src/LogInternal.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef PROTON_CPP_LOG_INTERNAL_H -#define PROTON_CPP_LOG_INTERNAL_H - -/* - * - * 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 "Msg.h" - -namespace proton { -namespace reactor { - -enum Level { trace, debug, info, notice, warning, error, critical }; - -class Logger -{ -public: - // TODO: build out to be ultra configurable as for corresponding QPID class + Statement - static void log(Level level, const char* file, int line, const char* function, const std::string& message); -private: - //This class has only one instance so no need to copy - Logger(); - ~Logger(); - - Logger(const Logger&); - Logger operator=(const Logger&); -}; - -// Just do simple logging for now -#define PN_CPP_LOG(LEVEL, MESSAGE) Logger::log(LEVEL, 0, 0, 0, ::proton::reactor::Msg() << MESSAGE) - -}} // namespace proton::reactor - -#endif /*!PROTON_CPP_LOG_INTERNAL_H*/ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/src/Logger.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/Logger.cpp b/proton-c/bindings/cpp/src/Logger.cpp deleted file mode 100644 index 2671b2e..0000000 --- a/proton-c/bindings/cpp/src/Logger.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * 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 "LogInternal.h" -#include <cstdlib> - -namespace proton { -namespace reactor { - -namespace { -bool levelSet = false; -Level logLevel = error; -Level getLogLevel() { - if (!levelSet) { - levelSet = true; - const char *l = getenv("PROTON_CPP_LOG_LEVEL"); - if (l && l[0] != 0 && l[1] == 0) { - char low = '0' + trace; - char high = '0' + critical; - if (*l >= low && *l <= high) - logLevel = (Level) (*l - '0'); - } - } - return logLevel; -} - -} // namespace - - -void Logger::log(Level level, const char* file, int line, const char* function, const std::string& message) -{ - if (level >= getLogLevel()) { - std::cout << message << std::endl; - std::cout.flush(); - } -} - -}} // namespace proton::reactor http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/8074793b/proton-c/bindings/cpp/src/exceptions.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/exceptions.cpp b/proton-c/bindings/cpp/src/exceptions.cpp deleted file mode 100644 index c19e61d..0000000 --- a/proton-c/bindings/cpp/src/exceptions.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * - * 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 "proton/cpp/exceptions.h" - -namespace proton { -namespace reactor { - -ProtonException::ProtonException(const std::string& msg) throw() : message(msg) {} -ProtonException::~ProtonException() throw() {} -const char* ProtonException::what() const throw() { return message.c_str(); } - -MessageReject::MessageReject(const std::string& msg) throw() : ProtonException(msg) {} -MessageRelease::MessageRelease(const std::string& msg) throw() : ProtonException(msg) {} - -}} // namespace proton::reactor --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
