GEODE-2484: Removes ACE_DLL (#591)
Replaces with boost::dll.
diff --git a/clicache/src/Utils.cpp b/clicache/src/Utils.cpp
index 8b54cce..4480b73 100644
--- a/clicache/src/Utils.cpp
+++ b/clicache/src/Utils.cpp
@@ -67,11 +67,6 @@
return nullptr;
}
- System::Int32 Utils::LastError::get( )
- {
- return apache::geode::client::Utils::getLastError( );
- }
-
} // namespace Client
} // namespace Geode
} // namespace Apache
diff --git a/clicache/src/Utils.hpp b/clicache/src/Utils.hpp
index bec8a6e..60b120b 100644
--- a/clicache/src/Utils.hpp
+++ b/clicache/src/Utils.hpp
@@ -37,50 +37,43 @@
/// <summary>
/// Some static utility methods.
/// </summary>
- public ref class Utils STATICCLASS
- {
- public:
+ public ref class Utils STATICCLASS
+ {
+ public:
- /// <summary>
- /// Load a method from the given assembly path using the default
- /// constructor (if not a static method) of the given type.
- /// </summary>
- /// <param name="assemblyPath">The path of the assembly.</param>
- /// <param name="typeName">
- /// The name of the class containing the method.
- /// </param>
- /// <param name="methodName">The name of the method.</param>
- /// <returns>
- /// The <c>System.Reflection.MethodInfo</c> for the given method,
- /// or null if the method is not found.
- /// </returns>
- static MethodInfo^ LoadMethod( String^ assemblyPath,
- String^ typeName, String^ methodName);
+ /// <summary>
+ /// Load a method from the given assembly path using the default
+ /// constructor (if not a static method) of the given type.
+ /// </summary>
+ /// <param name="assemblyPath">The path of the assembly.</param>
+ /// <param name="typeName">
+ /// The name of the class containing the method.
+ /// </param>
+ /// <param name="methodName">The name of the method.</param>
+ /// <returns>
+ /// The <c>System.Reflection.MethodInfo</c> for the given method,
+ /// or null if the method is not found.
+ /// </returns>
+ static MethodInfo^ LoadMethod( String^ assemblyPath,
+ String^ typeName, String^ methodName);
- /// <summary>
- /// Load a method from the given assembly name using the default
- /// constructor (if not a static method) of the given type.
- /// </summary>
- /// <param name="assemblyName">The name of the assembly.</param>
- /// <param name="typeName">
- /// The name of the class containing the method.
- /// </param>
- /// <param name="methodName">The name of the method.</param>
- /// <returns>
- /// The <c>System.Reflection.MethodInfo</c> for the given method,
- /// or null if the method is not found.
- /// </returns>
- static MethodInfo^ LoadMethodFrom( String^ assemblyName,
- String^ typeName, String^ methodName);
+ /// <summary>
+ /// Load a method from the given assembly name using the default
+ /// constructor (if not a static method) of the given type.
+ /// </summary>
+ /// <param name="assemblyName">The name of the assembly.</param>
+ /// <param name="typeName">
+ /// The name of the class containing the method.
+ /// </param>
+ /// <param name="methodName">The name of the method.</param>
+ /// <returns>
+ /// The <c>System.Reflection.MethodInfo</c> for the given method,
+ /// or null if the method is not found.
+ /// </returns>
+ static MethodInfo^ LoadMethodFrom( String^ assemblyName,
+ String^ typeName, String^ methodName);
- /// <summary>
- /// Utility method to get the calling thread's last system error code.
- /// </summary>
- static property System::Int32 LastError
- {
- System::Int32 get( );
- }
- };
+ };
} // namespace Client
} // namespace Geode
} // namespace Apache
diff --git a/cppcache/src/CacheXmlParser.hpp b/cppcache/src/CacheXmlParser.hpp
index 1353d33..439a00d 100644
--- a/cppcache/src/CacheXmlParser.hpp
+++ b/cppcache/src/CacheXmlParser.hpp
@@ -162,8 +162,8 @@
// this is a managed library
(loader)(libraryName.c_str(), functionName.c_str());
} else {
- apache::geode::client::Utils::getFactoryFunction(libraryName,
- functionName);
+ apache::geode::client::Utils::getFactoryFunction<void*()>(libraryName,
+ functionName);
}
} catch (IllegalArgumentException& ex) {
throw CacheXmlException(ex.what());
diff --git a/cppcache/src/RegionAttributes.cpp b/cppcache/src/RegionAttributes.cpp
index 32843c6..4276d71 100644
--- a/cppcache/src/RegionAttributes.cpp
+++ b/cppcache/src/RegionAttributes.cpp
@@ -67,9 +67,8 @@
m_cacheLoader.reset((CacheXmlParser::managedCacheLoaderFn_)(
m_cacheLoaderLibrary.c_str(), m_cacheLoaderFactory.c_str()));
} else {
- CacheLoader* (*funcptr)();
- funcptr = reinterpret_cast<CacheLoader* (*)()>(Utils::getFactoryFunction(
- m_cacheLoaderLibrary, m_cacheLoaderFactory));
+ auto funcptr = Utils::getFactoryFunction<CacheLoader*()>(
+ m_cacheLoaderLibrary, m_cacheLoaderFactory);
m_cacheLoader.reset(funcptr());
}
}
@@ -84,9 +83,8 @@
m_cacheWriter.reset((CacheXmlParser::managedCacheWriterFn_)(
m_cacheWriterLibrary.c_str(), m_cacheWriterFactory.c_str()));
} else {
- CacheWriter* (*funcptr)();
- funcptr = reinterpret_cast<CacheWriter* (*)()>(Utils::getFactoryFunction(
- m_cacheWriterLibrary, m_cacheWriterFactory));
+ auto funcptr = Utils::getFactoryFunction<CacheWriter*()>(
+ m_cacheWriterLibrary, m_cacheWriterFactory);
m_cacheWriter.reset(funcptr());
}
}
@@ -101,10 +99,8 @@
m_cacheListener.reset((CacheXmlParser::managedCacheListenerFn_)(
m_cacheListenerLibrary.c_str(), m_cacheListenerFactory.c_str()));
} else {
- CacheListener* (*funcptr)();
- funcptr =
- reinterpret_cast<CacheListener* (*)()>(Utils::getFactoryFunction(
- m_cacheListenerLibrary, m_cacheListenerFactory));
+ auto funcptr = Utils::getFactoryFunction<CacheListener*()>(
+ m_cacheListenerLibrary, m_cacheListenerFactory);
m_cacheListener.reset(funcptr());
}
}
@@ -121,10 +117,8 @@
m_partitionResolverLibrary.c_str(),
m_partitionResolverFactory.c_str()));
} else {
- PartitionResolver* (*funcptr)();
- funcptr =
- reinterpret_cast<PartitionResolver* (*)()>(Utils::getFactoryFunction(
- m_partitionResolverLibrary, m_partitionResolverFactory));
+ auto funcptr = Utils::getFactoryFunction<PartitionResolver*()>(
+ m_partitionResolverLibrary, m_partitionResolverFactory);
m_partitionResolver.reset(funcptr());
}
}
@@ -140,10 +134,8 @@
m_persistenceManager.reset((CacheXmlParser::managedPersistenceManagerFn_)(
m_persistenceLibrary.c_str(), m_persistenceFactory.c_str()));
} else {
- PersistenceManager* (*funcptr)();
- funcptr =
- reinterpret_cast<PersistenceManager* (*)()>(Utils::getFactoryFunction(
- m_persistenceLibrary, m_persistenceFactory));
+ auto funcptr = Utils::getFactoryFunction<PersistenceManager*()>(
+ m_persistenceLibrary, m_persistenceFactory);
m_persistenceManager.reset(funcptr());
}
}
diff --git a/cppcache/src/Utils.cpp b/cppcache/src/Utils.cpp
index b7b2c32..17227c5 100644
--- a/cppcache/src/Utils.cpp
+++ b/cppcache/src/Utils.cpp
@@ -21,18 +21,16 @@
#include <cstdio>
#include <cstdlib>
#include <iomanip>
-#include <sstream>
-#include <ace/DLL.h>
#include <ace/INET_Addr.h>
#include <ace/OS.h>
+#include <boost/asio.hpp>
+#include <boost/dll/import.hpp>
namespace apache {
namespace geode {
namespace client {
-int32_t Utils::getLastError() { return ACE_OS::last_error(); }
-
std::string Utils::getEnv(const char* varName) {
std::string env;
if (const auto varValue = std::getenv(varName)) {
@@ -151,18 +149,59 @@
return resStr;
}
-void* Utils::getFactoryFunction(const std::string& lib,
- const std::string& funcName) {
- ACE_DLL dll;
- if (dll.open(lib.c_str(), ACE_DEFAULT_SHLIB_MODE, 0) == -1) {
- throw IllegalArgumentException("cannot open library: " + lib);
+/**
+ * Finds, loads and keeps a copy of requested shared library. Future
+ * improvements should use the boost::dll::import to maintain references to
+ * shared libraries rather than a synchronized global structure.
+ *
+ * Uses similar options ans search patterns to the original ACE_DLL
+ * implementation.
+ *
+ * @param libraryName to find or load
+ * @return found or loaded shared library
+ * @throws IllegalArgumentException if library is not found or otherwise
+ * unloadable.
+ */
+const boost::dll::shared_library& getSharedLibrary(
+ const std::string& libraryName) {
+ static std::mutex sharedLibrariesMutex;
+ static std::unordered_map<std::string,
+ std::shared_ptr<boost::dll::shared_library>>
+ sharedLibraries;
+
+ std::lock_guard<decltype(sharedLibrariesMutex)> lock(sharedLibrariesMutex);
+
+ const auto& find = sharedLibraries.find(libraryName);
+ if (find == sharedLibraries.end()) {
+ try {
+ return *sharedLibraries
+ .emplace(
+ libraryName,
+ std::make_shared<boost::dll::shared_library>(
+ libraryName,
+ boost::dll::load_mode::rtld_global |
+ boost::dll::load_mode::rtld_lazy |
+ boost::dll::load_mode::append_decorations |
+ boost::dll::load_mode::search_system_folders))
+ .first->second;
+ } catch (const boost::dll::fs::system_error& e) {
+ throw IllegalArgumentException("cannot open library: " + libraryName +
+ ": reason: " + e.what());
+ }
}
- void* func = dll.symbol(funcName.c_str());
- if (func == nullptr) {
+
+ return *find->second;
+}
+
+void* Utils::getFactoryFunctionVoid(const std::string& lib,
+ const std::string& funcName) {
+ try {
+ const auto& sharedLibrary = getSharedLibrary(lib);
+ return reinterpret_cast<void*>(sharedLibrary.get<void*()>(funcName));
+ } catch (const boost::dll::fs::system_error&) {
throw IllegalArgumentException("cannot find factory function " + funcName +
" in library " + lib);
}
- return func;
}
std::string Utils::convertBytesToString(const uint8_t* bytes, size_t length,
diff --git a/cppcache/src/Utils.hpp b/cppcache/src/Utils.hpp
index ba9c80d..52a6041 100644
--- a/cppcache/src/Utils.hpp
+++ b/cppcache/src/Utils.hpp
@@ -58,7 +58,6 @@
* On windows the maximum length of value supported is 8191.
*/
static std::string getEnv(const char* varName);
- static int32_t getLastError();
#ifdef __GNUC__
inline static char* _gnuDemangledName(const char* typeIdName, size_t& len) {
@@ -167,14 +166,16 @@
size_t maxLength = _GF_MSG_LIMIT);
/**
- * lib should be in the form required by ACE_DLL, typically just like
- * specifying
- * a
- * lib in java System.loadLibrary( "x" ); Where x is a component of the name
- * lib<x>.so on unix, or <x>.dll on windows.
+ * lib should be in the form originally required by ACE_DLL, typically just
+ * like specifying a lib in java System.loadLibrary( "x" ); Where x is a
+ * component of the name lib<x>.so on unix, or <x>.dll on windows.
*/
- static void* getFactoryFunction(const std::string& lib,
- const std::string& funcName);
+ template <typename T>
+ static T* getFactoryFunction(const std::string& libraryName,
+ const std::string& functionName) {
+ return reinterpret_cast<T*>(
+ getFactoryFunctionVoid(libraryName, functionName));
+ }
/**
* Convert the byte array to a string as "%d %d ...".
@@ -192,6 +193,10 @@
return convertBytesToString(reinterpret_cast<const uint8_t*>(bytes), length,
maxLength);
}
+
+ private:
+ static void* getFactoryFunctionVoid(const std::string& lib,
+ const std::string& funcName);
};
// Generate random numbers 0 to max-1