1 /*------------------------------------------------------------------------------
2 Name: xmlBlaster/demo/c++/MultiConnectDemo.cpp
3 Project: xmlBlaster.org
4 Comment: C++ client example
5 Author: Marcel Ruff
6 ------------------------------------------------------------------------------*/
7 #include <client/XmlBlasterAccess.h>
8 #include <util/Global.h>
9 #include <vector>
10
11 using namespace std;
12 using namespace org::xmlBlaster::util;
13 using namespace org::xmlBlaster::util::qos;
14 using namespace org::xmlBlaster::util::dispatch;
15 using namespace org::xmlBlaster::client;
16 using namespace org::xmlBlaster::client::qos;
17 using namespace org::xmlBlaster::client::key;
18
19 /**
20 * Helper class to receive the connection specific callback messages.
21 * One instance of this will be used for each connection.
22 * <p>
23 * Additionally we listen on connection change events (for example if
24 * the xmlBlaster server disappears).
25 * </p>
26 */
27 class SpecificCallback : public I_Callback, public I_ConnectionProblems
28 {
29 private:
30 const string ME;
31 I_Log& log_;
32 public:
33 SpecificCallback(const GlobalRef global) : ME(global->getInstanceName()),
34 log_(global->getLog("MultiConnectDemo"))
35 {}
36
37 /**
38 * Callbacks from xmlBlaster arrive here.
39 */
40 string update(const string& sessionId, UpdateKey& updateKey,
41 const unsigned char* content,
42 long contentSize, UpdateQos& updateQos)
43 {
44 string contentStr(reinterpret_cast<char *>(const_cast<unsigned char *>(content)), contentSize);
45 log_.info(ME, "Received update message with secret sessionId '" + sessionId + "':" +
46 updateKey.toXml() +
47 "\n content=" + contentStr +
48 updateQos.toXml());
49 return "";
50 }
51
52 bool reachedAlive(StatesEnum /*oldState*/, I_ConnectionsHandler* /*connectionsHandler*/)
53 {
54 log_.info(ME, "reconnected");
55 return true;
56 }
57
58 void reachedDead(StatesEnum /*oldState*/, I_ConnectionsHandler* /*connectionsHandler*/)
59 {
60 log_.info(ME, "lost connection");
61 }
62
63 void reachedPolling(StatesEnum /*oldState*/, I_ConnectionsHandler* /*connectionsHandler*/)
64 {
65 log_.info(ME, "going to poll modus");
66 }
67 };
68
69
70 /**
71 * This client connects 5 times to xmlBlaster.
72 * <p>
73 * All five connections subscribe to a message, we then publish the message
74 * and receive it 5 times asynchronous in the connection specific update() method.
75 * </p>
76 * <pre>
77 * Invoke: MultiConnectDemo
78 * </pre>
79 * @see <a href="http://www.xmlBlaster.org/xmlBlaster/doc/requirements/interface.html"
80 * target="others">xmlBlaster interface</a>
81 */
82 class MultiConnectDemo
83 {
84 private:
85 string ME; /**< the string identifying this class when logging */
86 Global& global_; /**< The singleton Global instance, handled by Object_Lifetime_Manager */
87 I_Log& log_; /**< Logging output */
88
89 public:
90 MultiConnectDemo(Global& glob) : ME("MultiConnectDemo"), global_(glob),
91 log_(glob.getLog("MultiConnectDemo")) {}
92
93 virtual ~MultiConnectDemo() {}
94
95 void execute()
96 {
97 const int NUM_CONN = global_.getProperty().get("numConn", 10);
98 long sleepMillis = global_.getProperty().get("sleep", 1000L);
99 try {
100 vector<XmlBlasterAccessRef> connVec; // Holding all connections to xmlBlaster
101 // Connect 5 times to xmlBlaster
102 for (int i=0; i<NUM_CONN; i++) {
103 string instanceName = string("connection-") + lexical_cast<std::string>(i);
104 Property::MapType propMap;
105 propMap["session.name"] = instanceName; // Set a unique login name
106 GlobalRef globalRef = Global::getInstance().createInstance(instanceName, &propMap);
107 connVec.push_back(XmlBlasterAccessRef(new XmlBlasterAccess(globalRef)));
108
109 SpecificCallback* cbP = new SpecificCallback(globalRef);
110 //connVec[i]->initFailsafe(cbP);
111 ConnectQos qos(*globalRef);
112 ConnectReturnQos retQos = connVec[i]->connect(qos, cbP);
113 log_.info(ME, "Successfully connected to xmlBlaster as " +
114 retQos.getSessionQos().getSessionName()->getAbsoluteName());
115 }
116
117 // Subscribe 5 times
118 for (int i=0; i<NUM_CONN; i++) {
119 SubscribeKey subKey(connVec[i]->getGlobal());
120 subKey.setOid("MultiConnectDemo");
121 SubscribeQos subQos(connVec[i]->getGlobal());
122 log_.info(ME, "Subscribing to xmlBlaster"); // + subKey.toXml() +
123 SubscribeReturnQos subRetQos = connVec[i]->subscribe(subKey, subQos);
124 log_.info(ME, "Successfully subscribed to xmlBlaster: " + subRetQos.getSubscriptionId());
125 }
126
127 // Publish a message with the oid 'MultiConnectDemo'
128 // all subscribers should receive it
129 PublishQos publishQos(connVec[0]->getGlobal());
130 PublishKey publishKey(connVec[0]->getGlobal());
131 publishKey.setOid("MultiConnectDemo");
132 MessageUnit msgUnit(publishKey, string("Hi"), publishQos);
133 log_.info(ME, "Publishing to xmlBlaster");
134 PublishReturnQos pubRetQos = connVec[0]->publish(msgUnit);
135 log_.info(ME, "Successfully published to xmlBlaster: " + pubRetQos.getKeyOid());
136 try {
137 log_.info(ME, "Sleeping now for " + lexical_cast<string>(sleepMillis) + " msec ...");
138 org::xmlBlaster::util::thread::Thread::sleep(sleepMillis);
139 }
140 catch(const XmlBlasterException &e) {
141 log_.error(ME, e.toXml());
142 }
143
144 // Erase the topic
145 EraseKey eraseKey(connVec[0]->getGlobal());
146 eraseKey.setOid("MultiConnectDemo");
147 EraseQos eraseQos(connVec[0]->getGlobal());
148 log_.info(ME, "Erasing the published message");
149 connVec[0]->erase(eraseKey, eraseQos);
150
151 // Disconnect all clients
152 for (int i=0; i<NUM_CONN; i++) {
153 connVec[i]->disconnect(DisconnectQos(connVec[i]->getGlobal()));
154 delete connVec[i]->getCallback();
155 }
156
157 connVec.clear();
158 log_.info(ME, "Done, resources are released");
159 }
160 catch (const XmlBlasterException &e) {
161 log_.error(ME, e.toXml());
162 }
163 }
164 };
165
166 #include <iostream>
167
168 /**
169 * Try
170 * <pre>
171 * MultiConnectDemo -help
172 * </pre>
173 * for usage help
174 */
175 int main(int args, char ** argv)
176 {
177 try {
178 org::xmlBlaster::util::Object_Lifetime_Manager::init();
179 Global& glob = Global::getInstance();
180 glob.initialize(args, argv);
181
182 string intro = "XmlBlaster C++ client " + glob.getReleaseId() +
183 ", try option '-help' if you need usage informations.";
184 glob.getLog().info("MultiConnectDemo", intro);
185
186 if (glob.wantsHelp()) {
187 cout << Global::usage() << endl;
188 cout << endl << "MultiConnectDemo";
189 cout << endl << " -sleep Sleep after publishing [1000 millisec]" << endl;
190 cout << endl << "Example:" << endl;
191 cout << endl << "MultiConnectDemo -trace true -sleep 2000";
192 cout << endl << "MultiConnectDemo -dispatch/connection/delay 10000 -sleep 2000000" << endl << endl;
193 org::xmlBlaster::util::Object_Lifetime_Manager::fini();
194 return 1;
195 }
196
197 MultiConnectDemo hello(glob);
198 hello.execute();
199 }
200 catch (XmlBlasterException &e) {
201 std::cerr << "Caught exception: " << e.getMessage() << std::endl;
202 }
203 catch (...) {
204 std::cerr << "Caught exception, exit" << std::endl;
205 }
206 org::xmlBlaster::util::Object_Lifetime_Manager::fini();
207 return 0;
208 }
syntax highlighted by Code2HTML, v. 0.9.1