1 /*------------------------------------------------------------------------------
  2 Name:      xmlBlaster/demo/c++/Leak.cpp
  3 Project:   xmlBlaster.org
  4 Comment:   Manually check for memory leaks (use for example valgrind to check)
  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 class SpecificCallback : public I_Callback
 20 {
 21  private:
 22    const string ME;
 23    I_Log& log_;
 24  public:
 25    SpecificCallback(const GlobalRef global) : ME(global->getInstanceName()),
 26                                               log_(global->getLog("Leak"))
 27    {}
 28 
 29    string update(const string& sessionId, UpdateKey& updateKey,
 30                  const unsigned char* content,
 31                  long contentSize, UpdateQos& updateQos)
 32    {
 33       string contentStr(reinterpret_cast<char *>(const_cast<unsigned char *>(content)), contentSize);
 34       log_.info(ME, "Received update message with secret sessionId '" + sessionId + "':" +
 35                     updateKey.toXml() +
 36                     "\n content=" + contentStr +
 37                     updateQos.toXml());
 38       return "";
 39    }
 40 };
 41 
 42 
 43 class Leak
 44 {
 45 private:
 46    string  ME;      /**< the string identifying this class when logging */
 47    Global& global_; /**< The singleton Global instance, handled by Object_Lifetime_Manager */
 48    I_Log& log_;     /**< Logging output */
 49    int count;
 50    bool holdReferenceCount;
 51 
 52 public:
 53    Leak(Global& glob) : ME("Leak"), global_(glob), 
 54                                     log_(glob.getLog("Leak")),
 55                                     count(5),
 56                                     holdReferenceCount(false) {
 57       count = global_.getProperty().get("count", count);
 58       holdReferenceCount = global_.getProperty().get("holdReferenceCount", holdReferenceCount);
 59    }
 60 
 61    virtual ~Leak() {}
 62 
 63    void checkGlobal()
 64    {
 65       log_.info(ME, "checkGlobal()");
 66       try {
 67          for (int i=0; i<count; i++) {
 68             string instanceName = string("connection-") + lexical_cast<std::string>(i);
 69             Property::MapType propMap;
 70             GlobalRef globalRef = global_.createInstance(instanceName, &propMap, holdReferenceCount);
 71             log_.info(ME, "Global created " + globalRef->getId());
 72             if (holdReferenceCount)
 73                global_.destroyInstance(instanceName);
 74          }
 75       }
 76       catch (const XmlBlasterException &e) {
 77          log_.error(ME, e.toXml());
 78       }
 79    }
 80 
 81    void checkGlobal2()
 82    {
 83       log_.info(ME, "checkGlobal2()");
 84       vector<GlobalRef> globVec; // Holding all connections to xmlBlaster
 85       try {
 86          for (int i=0; i<count; i++) {
 87             string instanceName = string("connection-") + lexical_cast<std::string>(i);
 88             Property::MapType propMap;
 89             GlobalRef globalRef = global_.createInstance(instanceName, &propMap, holdReferenceCount);
 90             globVec.push_back(globalRef);
 91             log_.info(ME, "Global created " + globalRef->getId());
 92             if (holdReferenceCount)
 93                global_.destroyInstance(instanceName);
 94          }
 95          for (int i=0; i<count; i++) {
 96             GlobalRef globalRef = globVec[i];
 97             log_.info(ME, "Global destroy " + globalRef->getId());
 98             if (holdReferenceCount)
 99                global_.destroyInstance(globalRef->getInstanceName());
100          }
101          globVec.clear();
102       }
103       catch (const XmlBlasterException &e) {
104          log_.error(ME, e.toXml());
105       }
106    }
107 
108    void checkConnection()
109    {
110       log_.info(ME, "checkConnection()");
111       try {
112          for (int i=0; i<count; i++) {
113             string instanceName = string("connection-") + lexical_cast<std::string>(i);
114             Property::MapType propMap;
115             GlobalRef globalRef = global_.createInstance(instanceName, &propMap);
116             XmlBlasterAccessRef con = XmlBlasterAccessRef(new XmlBlasterAccess(globalRef));
117             SpecificCallback* cbP = new SpecificCallback(globalRef);
118             ConnectQos qos(*globalRef);
119             ConnectReturnQos retQos = con->connect(qos, cbP);
120             log_.info(ME, "Successfully connected to xmlBlaster as " +
121                       retQos.getSessionQos().getSessionName()->getAbsoluteName());
122             con->disconnect(DisconnectQos(con->getGlobal()));
123             delete con->getCallback();  // same as *cbP
124          }
125       }
126       catch (const XmlBlasterException &e) {
127          log_.error(ME, e.toXml());
128       }
129    }
130 
131    // Using the pointers seems to leak memory -> this issue is not yet resolved!
132    void checkConnection2()
133    {
134       log_.info(ME, "checkConnection2()");
135       try {
136          XmlBlasterAccess** refs;
137          refs = new XmlBlasterAccess*[count];
138          for (int i=0; i<count; i++) {
139             string instanceName = string("connection2-") + lexical_cast<std::string>(i);
140             Property::MapType propMap;
141             GlobalRef globalRef = global_.createInstance(instanceName, &propMap);
142             XmlBlasterAccess* con = new XmlBlasterAccess(globalRef);
143             refs[i] = con;
144             SpecificCallback* cbP = new SpecificCallback(globalRef);
145             ConnectQos qos(*globalRef);
146             ConnectReturnQos retQos = con->connect(qos, cbP);
147             log_.info(ME, "Successfully connected to xmlBlaster as " +
148                       retQos.getSessionQos().getSessionName()->getAbsoluteName());
149          }
150          for (int i=0; i<count; i++) {
151             XmlBlasterAccess* con = refs[i];
152             con->disconnect(DisconnectQos(con->getGlobal()));
153             delete con->getCallback();  // same as *cbP
154             delete con;
155          }
156          delete [] refs;
157       }
158       catch (const XmlBlasterException &e) {
159          log_.error(ME, e.toXml());
160       }
161    }
162 
163    // Using the vector seems to leak memory -> this issue is not yet resolved!
164    void checkConnection3()
165    {
166       log_.info(ME, "checkConnection3()");
167       try {
168          vector<XmlBlasterAccessRef> connVec; // Holding all connections to xmlBlaster
169          for (int i=0; i<count; i++) {
170             string instanceName = string("connection2-") + lexical_cast<std::string>(i);
171             Property::MapType propMap;
172             GlobalRef globalRef = global_.createInstance(instanceName, &propMap);
173             XmlBlasterAccessRef con = XmlBlasterAccessRef(new XmlBlasterAccess(globalRef));
174             connVec.push_back(con);
175             SpecificCallback* cbP = new SpecificCallback(globalRef);
176             ConnectQos qos(*globalRef);
177             ConnectReturnQos retQos = con->connect(qos, cbP);
178             log_.info(ME, "Successfully connected to xmlBlaster as " +
179                       retQos.getSessionQos().getSessionName()->getAbsoluteName());
180          }
181          for (int i=0; i<count; i++) {
182             XmlBlasterAccessRef con = connVec[i];
183             con->disconnect(DisconnectQos(con->getGlobal()));
184             delete con->getCallback();  // same as *cbP
185          }
186          connVec.erase(connVec.begin(), connVec.end());
187       }
188       catch (const XmlBlasterException &e) {
189          log_.error(ME, e.toXml());
190       }
191    }
192 };
193 
194 #include <iostream>
195 
196 /**
197  * Try
198  * <pre>
199  *   Leak -help
200  * </pre>
201  * for usage help
202  */
203 int main(int args, char ** argv)
204 {
205    try {
206       org::xmlBlaster::util::Object_Lifetime_Manager::init();
207       Global& glob = Global::getInstance();
208       glob.initialize(args, argv);
209       
210       string intro = "XmlBlaster C++ client " + glob.getReleaseId() +
211                      ", try option '-help' if you need usage informations.";
212       glob.getLog().info("Leak", intro);
213 
214       if (glob.wantsHelp()) {
215          cout << Global::usage() << endl;
216          cout << endl << "Leak";
217          cout << endl << "   -sleep              Sleep after publishing [1000 millisec]" << endl;
218          cout << endl << "Example:" << endl;
219          cout << endl << "Leak -trace true -sleep 2000";
220          cout << endl << "Leak -dispatch/connection/delay 10000 -sleep 2000000" << endl << endl;
221          org::xmlBlaster::util::Object_Lifetime_Manager::fini();
222          return 1;
223       }
224 
225       Leak hello(glob);
226       if (glob.getProperty().get("global", false))
227          hello.checkGlobal();
228       if (glob.getProperty().get("global2", false))
229          hello.checkGlobal2();
230       if (glob.getProperty().get("con", false))
231          hello.checkConnection();
232       if (glob.getProperty().get("con2", false))
233          hello.checkConnection2();
234       if (glob.getProperty().get("con3", false))
235          hello.checkConnection3();
236    }
237    catch (XmlBlasterException &e) {
238       std::cerr << "Caught exception: " << e.getMessage() << std::endl;
239    }
240    catch (...) {
241       std::cerr << "Caught exception, exit" << std::endl;
242    }
243    org::xmlBlaster::util::Object_Lifetime_Manager::fini();
244    return 0;
245 }


syntax highlighted by Code2HTML, v. 0.9.1