demo/c++/Leak.cpp

Go to the documentation of this file.
00001 /*------------------------------------------------------------------------------
00002 Name:      xmlBlaster/demo/c++/Leak.cpp
00003 Project:   xmlBlaster.org
00004 Comment:   Manually check for memory leaks (use for example valgrind to check)
00005 Author:    Marcel Ruff
00006 ------------------------------------------------------------------------------*/
00007 #include <client/XmlBlasterAccess.h>
00008 #include <util/Global.h>
00009 #include <vector>
00010 
00011 using namespace std;
00012 using namespace org::xmlBlaster::util;
00013 using namespace org::xmlBlaster::util::qos;
00014 using namespace org::xmlBlaster::util::dispatch;
00015 using namespace org::xmlBlaster::client;
00016 using namespace org::xmlBlaster::client::qos;
00017 using namespace org::xmlBlaster::client::key;
00018 
00019 class SpecificCallback : public I_Callback
00020 {
00021  private:
00022    const string ME;
00023    I_Log& log_;
00024  public:
00025    SpecificCallback(const GlobalRef global) : ME(global->getInstanceName()),
00026                                               log_(global->getLog("Leak"))
00027    {}
00028 
00029    string update(const string& sessionId, UpdateKey& updateKey,
00030                  const unsigned char* content,
00031                  long contentSize, UpdateQos& updateQos)
00032    {
00033       string contentStr(reinterpret_cast<char *>(const_cast<unsigned char *>(content)), contentSize);
00034       log_.info(ME, "Received update message with secret sessionId '" + sessionId + "':" +
00035                     updateKey.toXml() +
00036                     "\n content=" + contentStr +
00037                     updateQos.toXml());
00038       return "";
00039    }
00040 };
00041 
00042 
00043 class Leak
00044 {
00045 private:
00046    string  ME;      
00047    Global& global_; 
00048    I_Log& log_;     
00049    int count;
00050    bool holdReferenceCount;
00051 
00052 public:
00053    Leak(Global& glob) : ME("Leak"), global_(glob), 
00054                                     log_(glob.getLog("Leak")),
00055                                     count(5),
00056                                     holdReferenceCount(false) {
00057       count = global_.getProperty().get("count", count);
00058       holdReferenceCount = global_.getProperty().get("holdReferenceCount", holdReferenceCount);
00059    }
00060 
00061    virtual ~Leak() {}
00062 
00063    void checkGlobal()
00064    {
00065       log_.info(ME, "checkGlobal()");
00066       try {
00067          for (int i=0; i<count; i++) {
00068             string instanceName = string("connection-") + lexical_cast<std::string>(i);
00069             Property::MapType propMap;
00070             GlobalRef globalRef = global_.createInstance(instanceName, &propMap, holdReferenceCount);
00071             log_.info(ME, "Global created " + globalRef->getId());
00072             if (holdReferenceCount)
00073                global_.destroyInstance(instanceName);
00074          }
00075       }
00076       catch (const XmlBlasterException &e) {
00077          log_.error(ME, e.toXml());
00078       }
00079    }
00080 
00081    void checkGlobal2()
00082    {
00083       log_.info(ME, "checkGlobal2()");
00084       vector<GlobalRef> globVec; // Holding all connections to xmlBlaster
00085       try {
00086          for (int i=0; i<count; i++) {
00087             string instanceName = string("connection-") + lexical_cast<std::string>(i);
00088             Property::MapType propMap;
00089             GlobalRef globalRef = global_.createInstance(instanceName, &propMap, holdReferenceCount);
00090             globVec.push_back(globalRef);
00091             log_.info(ME, "Global created " + globalRef->getId());
00092             if (holdReferenceCount)
00093                global_.destroyInstance(instanceName);
00094          }
00095          for (int i=0; i<count; i++) {
00096             GlobalRef globalRef = globVec[i];
00097             log_.info(ME, "Global destroy " + globalRef->getId());
00098             if (holdReferenceCount)
00099                global_.destroyInstance(globalRef->getInstanceName());
00100          }
00101          globVec.clear();
00102       }
00103       catch (const XmlBlasterException &e) {
00104          log_.error(ME, e.toXml());
00105       }
00106    }
00107 
00108    void checkConnection()
00109    {
00110       log_.info(ME, "checkConnection()");
00111       try {
00112          for (int i=0; i<count; i++) {
00113             string instanceName = string("connection-") + lexical_cast<std::string>(i);
00114             Property::MapType propMap;
00115             GlobalRef globalRef = global_.createInstance(instanceName, &propMap);
00116             XmlBlasterAccessRef con = XmlBlasterAccessRef(new XmlBlasterAccess(globalRef));
00117             SpecificCallback* cbP = new SpecificCallback(globalRef);
00118             ConnectQos qos(*globalRef);
00119             ConnectReturnQos retQos = con->connect(qos, cbP);
00120             log_.info(ME, "Successfully connected to xmlBlaster as " +
00121                       retQos.getSessionQos().getSessionName()->getAbsoluteName());
00122             con->disconnect(DisconnectQos(con->getGlobal()));
00123             delete con->getCallback();  // same as *cbP
00124          }
00125       }
00126       catch (const XmlBlasterException &e) {
00127          log_.error(ME, e.toXml());
00128       }
00129    }
00130 
00131    // Using the pointers seems to leak memory -> this issue is not yet resolved!
00132    void checkConnection2()
00133    {
00134       log_.info(ME, "checkConnection2()");
00135       try {
00136          XmlBlasterAccess** refs;
00137          refs = new XmlBlasterAccess*[count];
00138          for (int i=0; i<count; i++) {
00139             string instanceName = string("connection2-") + lexical_cast<std::string>(i);
00140             Property::MapType propMap;
00141             GlobalRef globalRef = global_.createInstance(instanceName, &propMap);
00142             XmlBlasterAccess* con = new XmlBlasterAccess(globalRef);
00143             refs[i] = con;
00144             SpecificCallback* cbP = new SpecificCallback(globalRef);
00145             ConnectQos qos(*globalRef);
00146             ConnectReturnQos retQos = con->connect(qos, cbP);
00147             log_.info(ME, "Successfully connected to xmlBlaster as " +
00148                       retQos.getSessionQos().getSessionName()->getAbsoluteName());
00149          }
00150          for (int i=0; i<count; i++) {
00151             XmlBlasterAccess* con = refs[i];
00152             con->disconnect(DisconnectQos(con->getGlobal()));
00153             delete con->getCallback();  // same as *cbP
00154             delete con;
00155          }
00156          delete [] refs;
00157       }
00158       catch (const XmlBlasterException &e) {
00159          log_.error(ME, e.toXml());
00160       }
00161    }
00162 
00163    // Using the vector seems to leak memory -> this issue is not yet resolved!
00164    void checkConnection3()
00165    {
00166       log_.info(ME, "checkConnection3()");
00167       try {
00168          vector<XmlBlasterAccessRef> connVec; // Holding all connections to xmlBlaster
00169          for (int i=0; i<count; i++) {
00170             string instanceName = string("connection2-") + lexical_cast<std::string>(i);
00171             Property::MapType propMap;
00172             GlobalRef globalRef = global_.createInstance(instanceName, &propMap);
00173             XmlBlasterAccessRef con = XmlBlasterAccessRef(new XmlBlasterAccess(globalRef));
00174             connVec.push_back(con);
00175             SpecificCallback* cbP = new SpecificCallback(globalRef);
00176             ConnectQos qos(*globalRef);
00177             ConnectReturnQos retQos = con->connect(qos, cbP);
00178             log_.info(ME, "Successfully connected to xmlBlaster as " +
00179                       retQos.getSessionQos().getSessionName()->getAbsoluteName());
00180          }
00181          for (int i=0; i<count; i++) {
00182             XmlBlasterAccessRef con = connVec[i];
00183             con->disconnect(DisconnectQos(con->getGlobal()));
00184             delete con->getCallback();  // same as *cbP
00185          }
00186          connVec.erase(connVec.begin(), connVec.end());
00187       }
00188       catch (const XmlBlasterException &e) {
00189          log_.error(ME, e.toXml());
00190       }
00191    }
00192 };
00193 
00194 #include <iostream>
00195 
00203 int main(int args, char ** argv)
00204 {
00205    try {
00206       org::xmlBlaster::util::Object_Lifetime_Manager::init();
00207       Global& glob = Global::getInstance();
00208       glob.initialize(args, argv);
00209       
00210       string intro = "XmlBlaster C++ client " + glob.getReleaseId() +
00211                      ", try option '-help' if you need usage informations.";
00212       glob.getLog().info("Leak", intro);
00213 
00214       if (glob.wantsHelp()) {
00215          cout << Global::usage() << endl;
00216          cout << endl << "Leak";
00217          cout << endl << "   -sleep              Sleep after publishing [1000 millisec]" << endl;
00218          cout << endl << "Example:" << endl;
00219          cout << endl << "Leak -trace true -sleep 2000";
00220          cout << endl << "Leak -dispatch/connection/delay 10000 -sleep 2000000" << endl << endl;
00221          org::xmlBlaster::util::Object_Lifetime_Manager::fini();
00222          return 1;
00223       }
00224 
00225       Leak hello(glob);
00226       if (glob.getProperty().get("global", false))
00227          hello.checkGlobal();
00228       if (glob.getProperty().get("global2", false))
00229          hello.checkGlobal2();
00230       if (glob.getProperty().get("con", false))
00231          hello.checkConnection();
00232       if (glob.getProperty().get("con2", false))
00233          hello.checkConnection2();
00234       if (glob.getProperty().get("con3", false))
00235          hello.checkConnection3();
00236    }
00237    catch (XmlBlasterException &e) {
00238       std::cerr << "Caught exception: " << e.getMessage() << std::endl;
00239    }
00240    catch (...) {
00241       std::cerr << "Caught exception, exit" << std::endl;
00242    }
00243    org::xmlBlaster::util::Object_Lifetime_Manager::fini();
00244    return 0;
00245 }