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 }