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