[PATCH 1/3] [MAMAC] mamaPlugin Feature
Gary Molloy <g.molloy@...>
Testing Strategy:- Using the attached template you can create your own plugin and load it in via your mama.properties, for example:
mama.plugin.name_0=template
You can run up a mamaPublisher to test your plugin, for example:
mamapublisherc -tport pub -m wmw -l MAMA_INBOUND_TOPIC -v -v -v -v -v
You can expect to see output similar this if your plugin was loaded successfully:
2015-04-09 13:45:02: (f9018280) : mama_initPlugins(): Initialising [mama.plugin.name_0] template 2015-04-09 13:45:02: (f9018280) : mama_loadPlugin(): Sucessfully registered plugin functions for [template] 2015-04-09 13:45:02: (f9018280) : mama_loadPlugin(): Successfully run the init hook for mama plugin [template]
If your plugin was not loaded successful you can expect to see output similar to this:
2015-04-09 13:45:02: (f9018280) : mama_initPlugins(): Initialising [mama.plugin.name_0] template 2015-04-09 13:45:02: (f9018280) : mamaPlugin_registerFunctions(): Cannot load plugin, does not implement required function: [templateMamaPlugin_shutdownHook] 2015-04-09 13:45:02: (f9018280) : mama_loadPlugin(): Failed to register plugin functions for [template]
Further documentation on the mamaPlugin feature will be available shortly which will provide more details on the feature which will include the various hooks available etc...
=========================================================================================================
From e2a6a3f9c5750cee780cb6185a1310b4e4b70629 Mon Sep 17 00:00:00 2001 From: Gary Molloy <g.molloy@...> Date: Thu, 23 Apr 2015 11:22:14 -0400 Subject: [PATCH 1/3] [MAMAC] mamaPlugin Feature
A new feature, mamaPlugin has been introduced that will allow you to create and run your own code within 'hooks' into the MAMA codebase.
A mamaPlugin is essentially a shared object.
Signed-off-by: Gary Molloy <g.molloy@...> --- mama/c_cpp/src/c/Makefile.am | 1 + mama/c_cpp/src/c/SConscript | 1 + mama/c_cpp/src/c/SConscript.win | 1 + mama/c_cpp/src/c/mama.c | 10 +- mama/c_cpp/src/c/mama/types.h | 10 + mama/c_cpp/src/c/plugin.c | 472 +++++++++++++++++++++++++++++++++++++++ mama/c_cpp/src/c/plugin.h | 59 +++++ mama/c_cpp/src/c/publisher.c | 10 + mama/c_cpp/src/c/transport.c | 21 ++- 9 files changed, 579 insertions(+), 6 deletions(-) create mode 100644 mama/c_cpp/src/c/plugin.c create mode 100644 mama/c_cpp/src/c/plugin.h
diff --git a/mama/c_cpp/src/c/Makefile.am b/mama/c_cpp/src/c/Makefile.am index c831ce4..318c353 100644 --- a/mama/c_cpp/src/c/Makefile.am +++ b/mama/c_cpp/src/c/Makefile.am @@ -131,6 +131,7 @@ libmama_la_SOURCES = \ mamaStrUtils.h \ mamaStrUtils.c \ marketdata.c \ + plugin.c \ middleware.c \ msg.c \ msgfield.c \ diff --git a/mama/c_cpp/src/c/SConscript b/mama/c_cpp/src/c/SConscript index 4362f50..f47e18c 100644 --- a/mama/c_cpp/src/c/SConscript +++ b/mama/c_cpp/src/c/SConscript @@ -98,6 +98,7 @@ libmama_sources = \ mama.c mamaStrUtils.c marketdata.c + plugin.c middleware.c msg.c msgfield.c diff --git a/mama/c_cpp/src/c/SConscript.win b/mama/c_cpp/src/c/SConscript.win index 77e3e18..9a6ff05 100644 --- a/mama/c_cpp/src/c/SConscript.win +++ b/mama/c_cpp/src/c/SConscript.win @@ -50,6 +50,7 @@ dqpublishermanager.c inbox.c msgtype.c msgutils.c +plugin.c senderId.c reservedfields.c subscription.c diff --git a/mama/c_cpp/src/c/mama.c b/mama/c_cpp/src/c/mama.c index 33a0768..5e31856 100644 --- a/mama/c_cpp/src/c/mama.c +++ b/mama/c_cpp/src/c/mama.c @@ -35,6 +35,7 @@ #include <payloadbridge.h> #include <property.h> #include <platform.h> +#include <plugin.h> #include "fileutils.h" #include "reservedfieldsimpl.h" @@ -42,7 +43,6 @@ #include <mama/stat.h> #include <mama/statfields.h> #include <statsgeneratorinternal.h> -#include <statsgeneratorinternal.h> #include <mama/statscollector.h> #include "transportimpl.h" @@ -740,6 +740,9 @@ mama_openWithPropertiesCount (const char* path, } } + /* This will initialise all plugins */ + mama_initPlugins(); + prop = properties_Get (gProperties, "mama.catchcallbackexceptions.enable"); if (prop != NULL && strtobool(prop)) { @@ -1253,9 +1256,12 @@ mama_closeCount (unsigned int* count) gImpl.myPayloadLibraries[(uint8_t)payload] = NULL; } } - + gDefaultPayload = NULL; + /* This will shutdown all plugins */ + mama_shutdownPlugins(); + /* Look for a bridge for each of the middlewares and close them */ for (middleware = 0; middleware != MAMA_MIDDLEWARE_MAX; ++middleware) { diff --git a/mama/c_cpp/src/c/mama/types.h b/mama/c_cpp/src/c/mama/types.h index 50d6608..03f6da8 100644 --- a/mama/c_cpp/src/c/mama/types.h +++ b/mama/c_cpp/src/c/mama/types.h @@ -74,6 +74,16 @@ typedef struct mamaBridgeImpl_* mamaBridge; typedef struct mamaPayloadBridgeImpl_* mamaPayloadBridge; /** + * @brief Container for holding a mama plugin object + */ +typedef struct mamaPluginImpl_* mamaPlugin; + +/** + * @brief Container for holding a mama plugin info + */ +typedef void* mamaPluginInfo; + +/** * Flexible date/time format */ typedef mama_u64_t* mamaDateTime; diff --git a/mama/c_cpp/src/c/plugin.c b/mama/c_cpp/src/c/plugin.c new file mode 100644 index 0000000..b6475fe --- /dev/null +++ b/mama/c_cpp/src/c/plugin.c @@ -0,0 +1,472 @@ +/* $Id$ + * + * OpenMAMA: The open middleware agnostic messaging API + * Copyright (C) 2011 NYSE Technologies, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include <string.h> +#include <stdio.h> +#include <limits.h> + +#include "wombat/port.h" +#include "wombat/environment.h" +#include "wombat/strutils.h" +#include <wombat/wtable.h> + +#include <mama/mama.h> +#include <mama/error.h> +#include <mamainternal.h> +#include <mama/version.h> +#include <property.h> +#include <plugin.h> +#include <platform.h> + +#define PLUGIN_PROPERTY "mama.plugin.name_" +#define PLUGIN_NAME "mamaplugin" + +#define MAX_PLUGINS 100 +#define MAX_PLUGIN_STRING 1024 + +#define MAX_FUNC_STRING 256 + +/** + * @brief Mechanism for registering required plugin functions. + * + * Taking a function string name search the shared library handle, using the + * loadLibFunc portability method, for the function. If it is found, set the + * appropriate function pointer in the plugin struct to the result. If not, + * log as an error the fact that the funciton cannot be found, and return + * MAMA_STATUS_PLATFORM + * + * @param FUNCSTRINGNAME The string function name. + * @param FUNCIMPLNAME The name of the function pointer in the plugin struct + * @param FUNCIMPLTYPE The type of the function pointer expected. + */ +#define REGISTER_PLUGIN_FUNCTION(FUNCSTRINGNAME, FUNCIMPLNAME, FUNCIMPLTYPE) \ +do { \ + snprintf (functionName, MAX_FUNC_STRING, "%s"#FUNCSTRINGNAME, name); \ + result = loadLibFunc (pluginLib, functionName); \ + \ + if (NULL != result) { \ + (pluginImpl)->FUNCIMPLNAME = *(FUNCIMPLTYPE*)&result; \ + result = NULL; \ + } else { \ + mama_log (MAMA_LOG_LEVEL_ERROR, \ + "mamaPlugin_registerFunctions(): " \ + "Cannot load plugin, does not implement required function: [%s]",\ + functionName); \ + status = MAMA_STATUS_PLATFORM; \ + return status; \ + } \ +} while (0) + +/** + * @brief Mechanism for registering required plugin functions. + * + * Taking a function string name search the shared library handle, using the + * loadLibFunc portability method, for the function. If it is found, set the + * appropriate function pointer in the plugin struct to the result. If not + * log the fact that the function has not been found, and continue. + * + * @param FUNCSTRINGNAME The string function name. + * @param FUNCIMPLNAME The name of the function pointer in the plugin struct + * @param FUNCIMPLTYPE The type of the function pointer expected. + */ +#define REGISTER_OPTIONAL_PLUGIN_FUNCTION(FUNCSTRINGNAME, \ + FUNCIMPLNAME, \ + FUNCIMPLTYPE) \ +do { \ + snprintf (functionName, MAX_FUNC_STRING, "%s"#FUNCSTRINGNAME, name); \ + result = loadLibFunc (pluginLib, functionName); \ + \ + if (NULL != result) { \ + (pluginImpl)->FUNCIMPLNAME = *(FUNCIMPLTYPE*)&result; \ + result = NULL; \ + } else { \ + mama_log (MAMA_LOG_LEVEL_FINE, \ + "mamaPlugin_registerFunctions(): " \ + "Optional plugin function [%s] not found. Unavailable.", \ + functionName); \ + } \ +} while (0) + +typedef struct mamaPluginImpl_ +{ + LIB_HANDLE mPluginHandle; + char* mPluginName; + mamaPluginInfo mPluginInfo; + + mamaPlugin_publisherPreSendHook mamaPluginPublisherPreSendHook; + mamaPlugin_transportPostCreateHook mamaPluginTransportPostCreateHook; + mamaPlugin_shutdownHook mamaPluginShutdownHook; + mamaPlugin_initHook mamaPluginInitHook; + +} mamaPluginImpl; + +static mamaPluginImpl* gPlugins[MAX_PLUGINS]; +static volatile int gPluginNo = 0; + +/** + * @brief Used to load register all possible plugin functions to be + * used within Mama. + * + * param[in] pluginLib + * param[in] name + * param[in] pluginImpl The plugin impl to be used + * + * @return mama_status return code can be one of: + * MAMA_STATUS_OK + */ +mama_status +mamaPlugin_registerFunctions (LIB_HANDLE pluginLib, + const char* name, + mamaPluginInfo pluginInfo, + mamaPluginImpl* pluginImpl); + +/** + * @brief Used find a plugin using the library name + * + * param[in] name + * + * @return a valid mamaPluginImpl if found + */ +mamaPluginImpl* +mamaPlugin_findPlugin (const char* name); + +/** + * @brief Used find a plugin using the library name + * + * param[in] pluginName + * + * @return mama_status return code can be one of: + * MAMA_STATUS_OK + */ +mama_status +mama_loadPlugin (const char* pluginName); + + +/** + * Register function pointers associated with a specific plugin. + */ +mama_status +mamaPlugin_registerFunctions (LIB_HANDLE pluginLib, + const char* name, + mamaPluginInfo pluginInfo, + mamaPluginImpl* pluginImpl) +{ + mama_status status = MAMA_STATUS_OK; + void* result = NULL; + char functionName[MAX_FUNC_STRING]; + + /* Save off some informatin on the plugin */ + pluginImpl->mPluginHandle = pluginLib; + pluginImpl->mPluginName = strdup(name); + pluginImpl->mPluginInfo = pluginInfo; + + + /* Required fuctions */ + REGISTER_PLUGIN_FUNCTION (MamaPlugin_initHook, mamaPluginInitHook, + mamaPlugin_initHook); + REGISTER_PLUGIN_FUNCTION (MamaPlugin_shutdownHook, mamaPluginShutdownHook, + mamaPlugin_shutdownHook); + + + /* Optional fuctions */ + REGISTER_OPTIONAL_PLUGIN_FUNCTION (MamaPlugin_publisherPreSendHook, mamaPluginPublisherPreSendHook, + mamaPlugin_publisherPreSendHook); + REGISTER_OPTIONAL_PLUGIN_FUNCTION (MamaPlugin_transportPostCreateHook, mamaPluginTransportPostCreateHook, + mamaPlugin_transportPostCreateHook); + + return status; +} + +mama_status +mama_initPlugins(void) +{ + int pluginCount = 0; + const char* prop = NULL; + char propString[MAX_PLUGIN_STRING]; + + for (pluginCount = 0; pluginCount < MAX_PLUGINS; pluginCount++) + { + snprintf(propString, MAX_PLUGIN_STRING, + PLUGIN_PROPERTY"%d", + pluginCount); + + prop = properties_Get (mamaInternal_getProperties (), propString); + if (prop != NULL && strlen(prop)!= 0) + { + mama_log (MAMA_LOG_LEVEL_FINE, "mama_initPlugins(): Initialising [%s] %s", propString, prop); + mama_loadPlugin (prop); + } + } + + mama_log (MAMA_LOG_LEVEL_FINE, "mama_initPlugins(): Initialising mamacenterprise"); + mama_loadPlugin ("mamacenterprise"); + + return MAMA_STATUS_OK; +} + +mama_status +mama_loadPlugin (const char* pluginName) +{ + LIB_HANDLE pluginLib = NULL; + mamaPluginImpl* pluginImpl = NULL; + mama_status status = MAMA_STATUS_OK; + mamaPluginInfo pluginInfo = NULL; + char loadPluginName [MAX_PLUGIN_STRING]; + mamaPluginImpl* aPluginImpl = NULL; + + if (!pluginName) + return MAMA_STATUS_NULL_ARG; + + pluginImpl = mamaPlugin_findPlugin(pluginName); + + /* + * Check to see if pluginImpl has already been loaded + */ + if (pluginImpl == NULL) + { + /* The plugin name should be of the format mamaplugin<name> */ + if (strncmp(pluginName, "mamacenterprise", MAX_PLUGIN_STRING) == 0) + snprintf(loadPluginName, MAX_PLUGIN_STRING, + "%s", + pluginName); + else + snprintf(loadPluginName, MAX_PLUGIN_STRING, + "%s%s", + PLUGIN_NAME, + pluginName); + + pluginLib = openSharedLib (loadPluginName, NULL); + + if (!pluginLib) + { + + mama_log (MAMA_LOG_LEVEL_ERROR, + "mama_loadPlugin(): " + "Could not open plugin library [%s] [%s]", + pluginName, + getLibError()); + return MAMA_STATUS_PLATFORM; + } + + /* Create structure to hold plugin information */ + aPluginImpl = (mamaPluginImpl*)calloc (1, sizeof(mamaPluginImpl)); + + status = mamaPlugin_registerFunctions (pluginLib, + pluginName, + pluginInfo, + aPluginImpl); + + if (MAMA_STATUS_OK == status) + { + mama_log (MAMA_LOG_LEVEL_NORMAL, + "mama_loadPlugin(): " + "Sucessfully registered plugin functions for [%s]", + pluginName); + + } + else + { + mama_log (MAMA_LOG_LEVEL_WARN, + "mama_loadPlugin(): " + "Failed to register plugin functions for [%s]", + pluginName); + + closeSharedLib (aPluginImpl->mPluginHandle); + + free ((char*)aPluginImpl->mPluginName); + free ((mamaPluginImpl*)aPluginImpl); + + return status; + } + + /* Invoke the init function */ + status = aPluginImpl->mamaPluginInitHook (aPluginImpl->mPluginInfo); + + if (MAMA_STATUS_OK == status) + { + mama_log (MAMA_LOG_LEVEL_NORMAL, + "mama_loadPlugin(): Successfully run the init hook for mama plugin [%s]", + aPluginImpl->mPluginName); + } + else + { + mama_log (MAMA_LOG_LEVEL_WARN, + "mama_loadPlugin(): Init hook failed for mama plugin [%s]", + aPluginImpl->mPluginName); + + closeSharedLib (aPluginImpl->mPluginHandle); + + free ((char*)aPluginImpl->mPluginName); + free ((mamaPluginImpl*)aPluginImpl); + + return status; + } + + /* Save off the plugin impl and increment the plugin counter */ + gPlugins[gPluginNo] = aPluginImpl; + gPluginNo++; + + } + else + { + mama_log (MAMA_LOG_LEVEL_NORMAL, + "mama_loadPlugin(): " + "Plugin [%s] has already been loaded and initialised", + pluginName); + } + + return MAMA_STATUS_OK; +} + +mama_status +mama_shutdownPlugins (void) +{ + mama_status status = MAMA_STATUS_OK; + int plugin = 0; + int ret = 0; + + for (plugin = 0; plugin <= gPluginNo; plugin++) + { + if (gPlugins[plugin]->mPluginHandle != NULL) + { + /* Fire the user shutdown hook first - if one is present */ + if (gPlugins[plugin]->mamaPluginShutdownHook != NULL) + { + gPlugins[plugin]->mamaPluginShutdownHook (gPlugins[plugin]->mPluginInfo); + } + + ret = closeSharedLib (gPlugins[plugin]->mPluginHandle); + if (0!=ret) + { + mama_log (MAMA_LOG_LEVEL_WARN, + "mama_shutdownPlugins(): Failed to close Mama Plugin [%s]", + gPlugins[plugin]->mPluginName); + } + else + { + mama_log (MAMA_LOG_LEVEL_WARN, + "mama_shutdownPlugins(): Mama Plugin [%s] successfully closed", + gPlugins[plugin]->mPluginName); + } + + free ((char*)gPlugins[plugin]->mPluginName); + free (gPlugins[plugin]); + gPlugins[plugin] = NULL; + } + } + return status; +} + +mama_status +mamaPlugin_firePublisherPreSendHook (mamaPublisher publisher, mamaMsg message) +{ + mama_status status = MAMA_STATUS_OK; + int plugin = 0; + + for (plugin = 0; plugin <= gPluginNo; plugin++) + { + if (gPlugins[plugin] != NULL) + { + if (gPlugins[plugin]->mamaPluginPublisherPreSendHook != NULL) + { + status = gPlugins[plugin]->mamaPluginPublisherPreSendHook (gPlugins[plugin]->mPluginInfo, publisher, message); + + if (MAMA_STATUS_OK != status) + { + mama_log (MAMA_LOG_LEVEL_WARN, + "mamaPlugin_firePublisherPreSendHook(): Publisher pre send hook failed for mama plugin [%s]", + gPlugins[plugin]->mPluginName); + } + } + } + } + return status; +} + +mama_status +mamaPlugin_fireTransportPostCreateHook (mamaTransport transport) +{ + mama_status status = MAMA_STATUS_OK; + int plugin = 0; + + for (plugin = 0; plugin <= gPluginNo; plugin++) + { + if (gPlugins[plugin] != NULL) + { + if (gPlugins[plugin]->mamaPluginTransportPostCreateHook != NULL) + { + status = gPlugins[plugin]->mamaPluginTransportPostCreateHook (gPlugins[plugin]->mPluginInfo, transport); + + if (MAMA_STATUS_OK != status) + { + mama_log (MAMA_LOG_LEVEL_WARN, + "mamaPlugin_fireTransportPostCreateHook(): Transport post create hook failed for mama plugin [%s]", + gPlugins[plugin]->mPluginName); + } + } + } + } + return status; +} + +mama_status +mamaPlugin_fireShutdownHook (void) +{ + mama_status status = MAMA_STATUS_OK; + int plugin = 0; + + for (plugin = 0; plugin <= gPluginNo; plugin++) + { + if (gPlugins[plugin] != NULL) + { + if (gPlugins[plugin]->mamaPluginShutdownHook != NULL) + { + status = gPlugins[plugin]->mamaPluginShutdownHook (gPlugins[plugin]->mPluginInfo); + + if (MAMA_STATUS_OK != status) + { + mama_log (MAMA_LOG_LEVEL_WARN, + "mamaPlugin_fireShutdownHook(): Shutdown hook failed for mama plugin [%s]", + gPlugins[plugin]->mPluginName); + } + } + } + } + return status; +} + +mamaPluginImpl* +mamaPlugin_findPlugin (const char* name) +{ + int plugin = 0; + + for (plugin = 0; plugin <= gPluginNo; plugin++) + { + if (gPlugins[plugin]) + { + if ((strncmp(gPlugins[plugin]->mPluginName, name, MAX_PLUGIN_STRING) == 0)) + { + return gPlugins[plugin]; + } + } + } + return NULL; +} diff --git a/mama/c_cpp/src/c/plugin.h b/mama/c_cpp/src/c/plugin.h new file mode 100644 index 0000000..df43b27 --- /dev/null +++ b/mama/c_cpp/src/c/plugin.h @@ -0,0 +1,59 @@ +/* $Id$ + * + * OpenMAMA: The open middleware agnostic messaging API + * Copyright (C) 2011 NYSE Technologies, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef PluginH__ +#define PluginH__ + + +/** + * @brief Containers used within the mama plugin + */ +typedef mama_status (*mamaPlugin_publisherPreSendHook) (mamaPluginInfo pluginInfo, mamaPublisher publisher, mamaMsg message); +typedef mama_status (*mamaPlugin_transportPostCreateHook) (mamaPluginInfo pluginInfo, mamaTransport transport); +typedef mama_status (*mamaPlugin_shutdownHook) (mamaPluginInfo pluginInfo); +typedef mama_status (*mamaPlugin_initHook) (mamaPluginInfo* pluginInfo); + +/** + * Initialize the internal plugin interface + * + * @return mama status code + */ +extern mama_status +mama_initPlugins (void); + +/** + * Shutdown the internal plugin interface + * + * @return mama status code + */ +extern mama_status +mama_shutdownPlugins (void); + +extern mama_status +mamaPlugin_firePublisherPreSendHook (mamaPublisher publisher, mamaMsg message); + +extern mama_status +mamaPlugin_fireTransportPostCreateHook (mamaTransport transport); + +extern mama_status +mamaPlugin_fireShutdownHook (void); + +#endif /* PluginH__ */ diff --git a/mama/c_cpp/src/c/publisher.c b/mama/c_cpp/src/c/publisher.c index 4612d17..6a7f92d 100644 --- a/mama/c_cpp/src/c/publisher.c +++ b/mama/c_cpp/src/c/publisher.c @@ -23,6 +23,7 @@ #include "mama/publisher.h" #include "bridge.h" +#include "plugin.h" #include "throttle.h" #include "transportimpl.h" @@ -245,6 +246,15 @@ mamaPublisher_send (mamaPublisher publisher, if (!impl->mMamaPublisherBridgeImpl) return MAMA_STATUS_INVALID_ARG; if (!impl->mBridgeImpl) return MAMA_STATUS_NO_BRIDGE_IMPL; + /* Calling plugin hook */ + status = mamaPlugin_firePublisherPreSendHook (publisher, msg); + if (MAMA_STATUS_OK != status) + { + mama_log (MAMA_LOG_LEVEL_ERROR, + "mamaPublisher_send(): PublisherPreSendHook failed. Not sending message."); + return status; + } + status = impl->mBridgeImpl->bridgeMamaPublisherSend (impl->mMamaPublisherBridgeImpl, msg); diff --git a/mama/c_cpp/src/c/transport.c b/mama/c_cpp/src/c/transport.c index 339dbc0..622f47d 100644 --- a/mama/c_cpp/src/c/transport.c +++ b/mama/c_cpp/src/c/transport.c @@ -25,6 +25,7 @@ #include "mama/mama.h" #include "throttle.h" +#include "plugin.h" #include "list.h" #include "transportimpl.h" #include "bridge.h" @@ -876,10 +877,22 @@ mamaTransport_create (mamaTransport transport, if ((!self->mDisableRefresh) && (!mamaTransportInternal_disableRefreshes(name))) { - return refreshTransport_create (&self->mRefreshTransport, - (mamaTransport)self, - self->mListeners, - self->mBridgeImpl); + status = refreshTransport_create (&self->mRefreshTransport, + (mamaTransport)self, + self->mListeners, + self->mBridgeImpl); + + if (MAMA_STATUS_OK != status) + return status; + } + + /* Calling plugin hook*/ + status = mamaPlugin_fireTransportPostCreateHook (transport); + if (MAMA_STATUS_OK != status) + { + mama_log (MAMA_LOG_LEVEL_ERROR, + "mamaTransport_create(): TransportPostCreateHook failed with a status of %s", + mamaStatus_stringForStatus(status)); } return MAMA_STATUS_OK; -- 1.7.1
Gary Molloy – SR Labs Adelaide Exchange | 24-26 Adelaide Street | Belfast | BT2 8GD
|
|
Glenn McClements <g.mcclements@...>
Thanks Gary.
To give some background on this change, it’s a first pass at a plugin framework that I hope to build on to allow OpenMAMA to become much more of a flexible framework.
The initial hooks were there because of an immediate need, but I’d like to get feedback on where else people would find hooks useful. One area which I’d like to explore is for pluggable entitlements. Using the plugin framework rather than the bridge mechanism:
- the plugins are already dynamic in the sense that any can be loaded at runtime
- there is the concept of optional functions, so that a plugin can implement as many or as few hooks as they wish. We can also add new hooks without breaking compatibility.
- the hooks are multi purpose, and multiple plugins can be called from the same hook
Thanks,
Glenn
From: Gary Molloy
Date: Thursday, 23 April 2015 17:53 To: "openmama-dev@..." Subject: [Openmama-dev] [PATCH 1/3] [MAMAC] mamaPlugin Feature Testing Strategy:- Using the attached template you can create your own plugin and load it in via your mama.properties, for example:
mama.plugin.name_0=template
You can run up a mamaPublisher to test your plugin, for example:
mamapublisherc -tport pub -m wmw -l MAMA_INBOUND_TOPIC -v -v -v -v -v
You can expect to see output similar this if your plugin was loaded successfully:
2015-04-09 13:45:02: (f9018280) : mama_initPlugins(): Initialising [mama.plugin.name_0] template 2015-04-09 13:45:02: (f9018280) : mama_loadPlugin(): Sucessfully registered plugin functions for [template] 2015-04-09 13:45:02: (f9018280) : mama_loadPlugin(): Successfully run the init hook for mama plugin [template]
If your plugin was not loaded successful you can expect to see output similar to this:
2015-04-09 13:45:02: (f9018280) : mama_initPlugins(): Initialising [mama.plugin.name_0] template 2015-04-09 13:45:02: (f9018280) : mamaPlugin_registerFunctions(): Cannot load plugin, does not implement required function: [templateMamaPlugin_shutdownHook] 2015-04-09 13:45:02: (f9018280) : mama_loadPlugin(): Failed to register plugin functions for [template]
Further documentation on the mamaPlugin feature will be available shortly which will provide more details on the feature which will include the various hooks available etc...
=========================================================================================================
From e2a6a3f9c5750cee780cb6185a1310b4e4b70629 Mon Sep 17 00:00:00 2001 From: Gary Molloy <g.molloy@...> Date: Thu, 23 Apr 2015 11:22:14 -0400 Subject: [PATCH 1/3] [MAMAC] mamaPlugin Feature
A new feature, mamaPlugin has been introduced that will allow you to create and run your own code within 'hooks' into the MAMA codebase.
A mamaPlugin is essentially a shared object.
Signed-off-by: Gary Molloy <g.molloy@...> --- mama/c_cpp/src/c/Makefile.am | 1 + mama/c_cpp/src/c/SConscript | 1 + mama/c_cpp/src/c/SConscript.win | 1 + mama/c_cpp/src/c/mama.c | 10 +- mama/c_cpp/src/c/mama/types.h | 10 + mama/c_cpp/src/c/plugin.c | 472 +++++++++++++++++++++++++++++++++++++++ mama/c_cpp/src/c/plugin.h | 59 +++++ mama/c_cpp/src/c/publisher.c | 10 + mama/c_cpp/src/c/transport.c | 21 ++- 9 files changed, 579 insertions(+), 6 deletions(-) create mode 100644 mama/c_cpp/src/c/plugin.c create mode 100644 mama/c_cpp/src/c/plugin.h
diff --git a/mama/c_cpp/src/c/Makefile.am b/mama/c_cpp/src/c/Makefile.am index c831ce4..318c353 100644 --- a/mama/c_cpp/src/c/Makefile.am +++ b/mama/c_cpp/src/c/Makefile.am @@ -131,6 +131,7 @@ libmama_la_SOURCES = \ mamaStrUtils.h \ mamaStrUtils.c \ marketdata.c \ + plugin.c \ middleware.c \ msg.c \ msgfield.c \ diff --git a/mama/c_cpp/src/c/SConscript b/mama/c_cpp/src/c/SConscript index 4362f50..f47e18c 100644 --- a/mama/c_cpp/src/c/SConscript +++ b/mama/c_cpp/src/c/SConscript @@ -98,6 +98,7 @@ libmama_sources = \ mama.c mamaStrUtils.c marketdata.c + plugin.c middleware.c msg.c msgfield.c diff --git a/mama/c_cpp/src/c/SConscript.win b/mama/c_cpp/src/c/SConscript.win index 77e3e18..9a6ff05 100644 --- a/mama/c_cpp/src/c/SConscript.win +++ b/mama/c_cpp/src/c/SConscript.win @@ -50,6 +50,7 @@ dqpublishermanager.c inbox.c msgtype.c msgutils.c +plugin.c senderId.c reservedfields.c subscription.c diff --git a/mama/c_cpp/src/c/mama.c b/mama/c_cpp/src/c/mama.c index 33a0768..5e31856 100644 --- a/mama/c_cpp/src/c/mama.c +++ b/mama/c_cpp/src/c/mama.c @@ -35,6 +35,7 @@ #include <payloadbridge.h> #include <property.h> #include <platform.h> +#include <plugin.h> #include "fileutils.h" #include "reservedfieldsimpl.h" @@ -42,7 +43,6 @@ #include <mama/stat.h> #include <mama/statfields.h> #include <statsgeneratorinternal.h> -#include <statsgeneratorinternal.h> #include <mama/statscollector.h> #include "transportimpl.h" @@ -740,6 +740,9 @@ mama_openWithPropertiesCount (const char* path, } } + /* This will initialise all plugins */ + mama_initPlugins(); + prop = properties_Get (gProperties, "mama.catchcallbackexceptions.enable"); if (prop != NULL && strtobool(prop)) { @@ -1253,9 +1256,12 @@ mama_closeCount (unsigned int* count) gImpl.myPayloadLibraries[(uint8_t)payload] = NULL; } } - + gDefaultPayload = NULL; + /* This will shutdown all plugins */ + mama_shutdownPlugins(); + /* Look for a bridge for each of the middlewares and close them */ for (middleware = 0; middleware != MAMA_MIDDLEWARE_MAX; ++middleware) { diff --git a/mama/c_cpp/src/c/mama/types.h b/mama/c_cpp/src/c/mama/types.h index 50d6608..03f6da8 100644 --- a/mama/c_cpp/src/c/mama/types.h +++ b/mama/c_cpp/src/c/mama/types.h @@ -74,6 +74,16 @@ typedef struct mamaBridgeImpl_* mamaBridge; typedef struct mamaPayloadBridgeImpl_* mamaPayloadBridge; /** + * @brief Container for holding a mama plugin object + */ +typedef struct mamaPluginImpl_* mamaPlugin; + +/** + * @brief Container for holding a mama plugin info + */ +typedef void* mamaPluginInfo; + +/** * Flexible date/time format */ typedef mama_u64_t* mamaDateTime; diff --git a/mama/c_cpp/src/c/plugin.c b/mama/c_cpp/src/c/plugin.c new file mode 100644 index 0000000..b6475fe --- /dev/null +++ b/mama/c_cpp/src/c/plugin.c @@ -0,0 +1,472 @@ +/* $Id$ + * + * OpenMAMA: The open middleware agnostic messaging API + * Copyright (C) 2011 NYSE Technologies, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include <string.h> +#include <stdio.h> +#include <limits.h> + +#include "wombat/port.h" +#include "wombat/environment.h" +#include "wombat/strutils.h" +#include <wombat/wtable.h> + +#include <mama/mama.h> +#include <mama/error.h> +#include <mamainternal.h> +#include <mama/version.h> +#include <property.h> +#include <plugin.h> +#include <platform.h> + +#define PLUGIN_PROPERTY "mama.plugin.name_" +#define PLUGIN_NAME "mamaplugin" + +#define MAX_PLUGINS 100 +#define MAX_PLUGIN_STRING 1024 + +#define MAX_FUNC_STRING 256 + +/** + * @brief Mechanism for registering required plugin functions. + * + * Taking a function string name search the shared library handle, using the + * loadLibFunc portability method, for the function. If it is found, set the + * appropriate function pointer in the plugin struct to the result. If not, + * log as an error the fact that the funciton cannot be found, and return + * MAMA_STATUS_PLATFORM + * + * @param FUNCSTRINGNAME The string function name. + * @param FUNCIMPLNAME The name of the function pointer in the plugin struct + * @param FUNCIMPLTYPE The type of the function pointer expected. + */ +#define REGISTER_PLUGIN_FUNCTION(FUNCSTRINGNAME, FUNCIMPLNAME, FUNCIMPLTYPE) \ +do { \ + snprintf (functionName, MAX_FUNC_STRING, "%s"#FUNCSTRINGNAME, name); \ + result = loadLibFunc (pluginLib, functionName); \ + \ + if (NULL != result) { \ + (pluginImpl)->FUNCIMPLNAME = *(FUNCIMPLTYPE*)&result; \ + result = NULL; \ + } else { \ + mama_log (MAMA_LOG_LEVEL_ERROR, \ + "mamaPlugin_registerFunctions(): " \ + "Cannot load plugin, does not implement required function: [%s]",\ + functionName); \ + status = MAMA_STATUS_PLATFORM; \ + return status; \ + } \ +} while (0) + +/** + * @brief Mechanism for registering required plugin functions. + * + * Taking a function string name search the shared library handle, using the + * loadLibFunc portability method, for the function. If it is found, set the + * appropriate function pointer in the plugin struct to the result. If not + * log the fact that the function has not been found, and continue. + * + * @param FUNCSTRINGNAME The string function name. + * @param FUNCIMPLNAME The name of the function pointer in the plugin struct + * @param FUNCIMPLTYPE The type of the function pointer expected. + */ +#define REGISTER_OPTIONAL_PLUGIN_FUNCTION(FUNCSTRINGNAME, \ + FUNCIMPLNAME, \ + FUNCIMPLTYPE) \ +do { \ + snprintf (functionName, MAX_FUNC_STRING, "%s"#FUNCSTRINGNAME, name); \ + result = loadLibFunc (pluginLib, functionName); \ + \ + if (NULL != result) { \ + (pluginImpl)->FUNCIMPLNAME = *(FUNCIMPLTYPE*)&result; \ + result = NULL; \ + } else { \ + mama_log (MAMA_LOG_LEVEL_FINE, \ + "mamaPlugin_registerFunctions(): " \ + "Optional plugin function [%s] not found. Unavailable.", \ + functionName); \ + } \ +} while (0) + +typedef struct mamaPluginImpl_ +{ + LIB_HANDLE mPluginHandle; + char* mPluginName; + mamaPluginInfo mPluginInfo; + + mamaPlugin_publisherPreSendHook mamaPluginPublisherPreSendHook; + mamaPlugin_transportPostCreateHook mamaPluginTransportPostCreateHook; + mamaPlugin_shutdownHook mamaPluginShutdownHook; + mamaPlugin_initHook mamaPluginInitHook; + +} mamaPluginImpl; + +static mamaPluginImpl* gPlugins[MAX_PLUGINS]; +static volatile int gPluginNo = 0; + +/** + * @brief Used to load register all possible plugin functions to be + * used within Mama. + * + * param[in] pluginLib + * param[in] name + * param[in] pluginImpl The plugin impl to be used + * + * @return mama_status return code can be one of: + * MAMA_STATUS_OK + */ +mama_status +mamaPlugin_registerFunctions (LIB_HANDLE pluginLib, + const char* name, + mamaPluginInfo pluginInfo, + mamaPluginImpl* pluginImpl); + +/** + * @brief Used find a plugin using the library name + * + * param[in] name + * + * @return a valid mamaPluginImpl if found + */ +mamaPluginImpl* +mamaPlugin_findPlugin (const char* name); + +/** + * @brief Used find a plugin using the library name + * + * param[in] pluginName + * + * @return mama_status return code can be one of: + * MAMA_STATUS_OK + */ +mama_status +mama_loadPlugin (const char* pluginName); + + +/** + * Register function pointers associated with a specific plugin. + */ +mama_status +mamaPlugin_registerFunctions (LIB_HANDLE pluginLib, + const char* name, + mamaPluginInfo pluginInfo, + mamaPluginImpl* pluginImpl) +{ + mama_status status = MAMA_STATUS_OK; + void* result = NULL; + char functionName[MAX_FUNC_STRING]; + + /* Save off some informatin on the plugin */ + pluginImpl->mPluginHandle = pluginLib; + pluginImpl->mPluginName = strdup(name); + pluginImpl->mPluginInfo = pluginInfo; + + + /* Required fuctions */ + REGISTER_PLUGIN_FUNCTION (MamaPlugin_initHook, mamaPluginInitHook, + mamaPlugin_initHook); + REGISTER_PLUGIN_FUNCTION (MamaPlugin_shutdownHook, mamaPluginShutdownHook, + mamaPlugin_shutdownHook); + + + /* Optional fuctions */ + REGISTER_OPTIONAL_PLUGIN_FUNCTION (MamaPlugin_publisherPreSendHook, mamaPluginPublisherPreSendHook, + mamaPlugin_publisherPreSendHook); + REGISTER_OPTIONAL_PLUGIN_FUNCTION (MamaPlugin_transportPostCreateHook, mamaPluginTransportPostCreateHook, + mamaPlugin_transportPostCreateHook); + + return status; +} + +mama_status +mama_initPlugins(void) +{ + int pluginCount = 0; + const char* prop = NULL; + char propString[MAX_PLUGIN_STRING]; + + for (pluginCount = 0; pluginCount < MAX_PLUGINS; pluginCount++) + { + snprintf(propString, MAX_PLUGIN_STRING, + PLUGIN_PROPERTY"%d", + pluginCount); + + prop = properties_Get (mamaInternal_getProperties (), propString); + if (prop != NULL && strlen(prop)!= 0) + { + mama_log (MAMA_LOG_LEVEL_FINE, "mama_initPlugins(): Initialising [%s] %s", propString, prop); + mama_loadPlugin (prop); + } + } + + mama_log (MAMA_LOG_LEVEL_FINE, "mama_initPlugins(): Initialising mamacenterprise"); + mama_loadPlugin ("mamacenterprise"); + + return MAMA_STATUS_OK; +} + +mama_status +mama_loadPlugin (const char* pluginName) +{ + LIB_HANDLE pluginLib = NULL; + mamaPluginImpl* pluginImpl = NULL; + mama_status status = MAMA_STATUS_OK; + mamaPluginInfo pluginInfo = NULL; + char loadPluginName [MAX_PLUGIN_STRING]; + mamaPluginImpl* aPluginImpl = NULL; + + if (!pluginName) + return MAMA_STATUS_NULL_ARG; + + pluginImpl = mamaPlugin_findPlugin(pluginName); + + /* + * Check to see if pluginImpl has already been loaded + */ + if (pluginImpl == NULL) + { + /* The plugin name should be of the format mamaplugin<name> */ + if (strncmp(pluginName, "mamacenterprise", MAX_PLUGIN_STRING) == 0) + snprintf(loadPluginName, MAX_PLUGIN_STRING, + "%s", + pluginName); + else + snprintf(loadPluginName, MAX_PLUGIN_STRING, + "%s%s", + PLUGIN_NAME, + pluginName); + + pluginLib = openSharedLib (loadPluginName, NULL); + + if (!pluginLib) + { + + mama_log (MAMA_LOG_LEVEL_ERROR, + "mama_loadPlugin(): " + "Could not open plugin library [%s] [%s]", + pluginName, + getLibError()); + return MAMA_STATUS_PLATFORM; + } + + /* Create structure to hold plugin information */ + aPluginImpl = (mamaPluginImpl*)calloc (1, sizeof(mamaPluginImpl)); + + status = mamaPlugin_registerFunctions (pluginLib, + pluginName, + pluginInfo, + aPluginImpl); + + if (MAMA_STATUS_OK == status) + { + mama_log (MAMA_LOG_LEVEL_NORMAL, + "mama_loadPlugin(): " + "Sucessfully registered plugin functions for [%s]", + pluginName); + + } + else + { + mama_log (MAMA_LOG_LEVEL_WARN, + "mama_loadPlugin(): " + "Failed to register plugin functions for [%s]", + pluginName); + + closeSharedLib (aPluginImpl->mPluginHandle); + + free ((char*)aPluginImpl->mPluginName); + free ((mamaPluginImpl*)aPluginImpl); + + return status; + } + + /* Invoke the init function */ + status = aPluginImpl->mamaPluginInitHook (aPluginImpl->mPluginInfo); + + if (MAMA_STATUS_OK == status) + { + mama_log (MAMA_LOG_LEVEL_NORMAL, + "mama_loadPlugin(): Successfully run the init hook for mama plugin [%s]", + aPluginImpl->mPluginName); + } + else + { + mama_log (MAMA_LOG_LEVEL_WARN, + "mama_loadPlugin(): Init hook failed for mama plugin [%s]", + aPluginImpl->mPluginName); + + closeSharedLib (aPluginImpl->mPluginHandle); + + free ((char*)aPluginImpl->mPluginName); + free ((mamaPluginImpl*)aPluginImpl); + + return status; + } + + /* Save off the plugin impl and increment the plugin counter */ + gPlugins[gPluginNo] = aPluginImpl; + gPluginNo++; + + } + else + { + mama_log (MAMA_LOG_LEVEL_NORMAL, + "mama_loadPlugin(): " + "Plugin [%s] has already been loaded and initialised", + pluginName); + } + + return MAMA_STATUS_OK; +} + +mama_status +mama_shutdownPlugins (void) +{ + mama_status status = MAMA_STATUS_OK; + int plugin = 0; + int ret = 0; + + for (plugin = 0; plugin <= gPluginNo; plugin++) + { + if (gPlugins[plugin]->mPluginHandle != NULL) + { + /* Fire the user shutdown hook first - if one is present */ + if (gPlugins[plugin]->mamaPluginShutdownHook != NULL) + { + gPlugins[plugin]->mamaPluginShutdownHook (gPlugins[plugin]->mPluginInfo); + } + + ret = closeSharedLib (gPlugins[plugin]->mPluginHandle); + if (0!=ret) + { + mama_log (MAMA_LOG_LEVEL_WARN, + "mama_shutdownPlugins(): Failed to close Mama Plugin [%s]", + gPlugins[plugin]->mPluginName); + } + else + { + mama_log (MAMA_LOG_LEVEL_WARN, + "mama_shutdownPlugins(): Mama Plugin [%s] successfully closed", + gPlugins[plugin]->mPluginName); + } + + free ((char*)gPlugins[plugin]->mPluginName); + free (gPlugins[plugin]); + gPlugins[plugin] = NULL; + } + } + return status; +} + +mama_status +mamaPlugin_firePublisherPreSendHook (mamaPublisher publisher, mamaMsg message) +{ + mama_status status = MAMA_STATUS_OK; + int plugin = 0; + + for (plugin = 0; plugin <= gPluginNo; plugin++) + { + if (gPlugins[plugin] != NULL) + { + if (gPlugins[plugin]->mamaPluginPublisherPreSendHook != NULL) + { + status = gPlugins[plugin]->mamaPluginPublisherPreSendHook (gPlugins[plugin]->mPluginInfo, publisher, message); + + if (MAMA_STATUS_OK != status) + { + mama_log (MAMA_LOG_LEVEL_WARN, + "mamaPlugin_firePublisherPreSendHook(): Publisher pre send hook failed for mama plugin [%s]", + gPlugins[plugin]->mPluginName); + } + } + } + } + return status; +} + +mama_status +mamaPlugin_fireTransportPostCreateHook (mamaTransport transport) +{ + mama_status status = MAMA_STATUS_OK; + int plugin = 0; + + for (plugin = 0; plugin <= gPluginNo; plugin++) + { + if (gPlugins[plugin] != NULL) + { + if (gPlugins[plugin]->mamaPluginTransportPostCreateHook != NULL) + { + status = gPlugins[plugin]->mamaPluginTransportPostCreateHook (gPlugins[plugin]->mPluginInfo, transport); + + if (MAMA_STATUS_OK != status) + { + mama_log (MAMA_LOG_LEVEL_WARN, + "mamaPlugin_fireTransportPostCreateHook(): Transport post create hook failed for mama plugin [%s]", + gPlugins[plugin]->mPluginName); + } + } + } + } + return status; +} + +mama_status +mamaPlugin_fireShutdownHook (void) +{ + mama_status status = MAMA_STATUS_OK; + int plugin = 0; + + for (plugin = 0; plugin <= gPluginNo; plugin++) + { + if (gPlugins[plugin] != NULL) + { + if (gPlugins[plugin]->mamaPluginShutdownHook != NULL) + { + status = gPlugins[plugin]->mamaPluginShutdownHook (gPlugins[plugin]->mPluginInfo); + + if (MAMA_STATUS_OK != status) + { + mama_log (MAMA_LOG_LEVEL_WARN, + "mamaPlugin_fireShutdownHook(): Shutdown hook failed for mama plugin [%s]", + gPlugins[plugin]->mPluginName); + } + } + } + } + return status; +} + +mamaPluginImpl* +mamaPlugin_findPlugin (const char* name) +{ + int plugin = 0; + + for (plugin = 0; plugin <= gPluginNo; plugin++) + { + if (gPlugins[plugin]) + { + if ((strncmp(gPlugins[plugin]->mPluginName, name, MAX_PLUGIN_STRING) == 0)) + { + return gPlugins[plugin]; + } + } + } + return NULL; +} diff --git a/mama/c_cpp/src/c/plugin.h b/mama/c_cpp/src/c/plugin.h new file mode 100644 index 0000000..df43b27 --- /dev/null +++ b/mama/c_cpp/src/c/plugin.h @@ -0,0 +1,59 @@ +/* $Id$ + * + * OpenMAMA: The open middleware agnostic messaging API + * Copyright (C) 2011 NYSE Technologies, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef PluginH__ +#define PluginH__ + + +/** + * @brief Containers used within the mama plugin + */ +typedef mama_status (*mamaPlugin_publisherPreSendHook) (mamaPluginInfo pluginInfo, mamaPublisher publisher, mamaMsg message); +typedef mama_status (*mamaPlugin_transportPostCreateHook) (mamaPluginInfo pluginInfo, mamaTransport transport); +typedef mama_status (*mamaPlugin_shutdownHook) (mamaPluginInfo pluginInfo); +typedef mama_status (*mamaPlugin_initHook) (mamaPluginInfo* pluginInfo); + +/** + * Initialize the internal plugin interface + * + * @return mama status code + */ +extern mama_status +mama_initPlugins (void); + +/** + * Shutdown the internal plugin interface + * + * @return mama status code + */ +extern mama_status +mama_shutdownPlugins (void); + +extern mama_status +mamaPlugin_firePublisherPreSendHook (mamaPublisher publisher, mamaMsg message); + +extern mama_status +mamaPlugin_fireTransportPostCreateHook (mamaTransport transport); + +extern mama_status +mamaPlugin_fireShutdownHook (void); + +#endif /* PluginH__ */ diff --git a/mama/c_cpp/src/c/publisher.c b/mama/c_cpp/src/c/publisher.c index 4612d17..6a7f92d 100644 --- a/mama/c_cpp/src/c/publisher.c +++ b/mama/c_cpp/src/c/publisher.c @@ -23,6 +23,7 @@ #include "mama/publisher.h" #include "bridge.h" +#include "plugin.h" #include "throttle.h" #include "transportimpl.h" @@ -245,6 +246,15 @@ mamaPublisher_send (mamaPublisher publisher, if (!impl->mMamaPublisherBridgeImpl) return MAMA_STATUS_INVALID_ARG; if (!impl->mBridgeImpl) return MAMA_STATUS_NO_BRIDGE_IMPL; + /* Calling plugin hook */ + status = mamaPlugin_firePublisherPreSendHook (publisher, msg); + if (MAMA_STATUS_OK != status) + { + mama_log (MAMA_LOG_LEVEL_ERROR, + "mamaPublisher_send(): PublisherPreSendHook failed. Not sending message."); + return status; + } + status = impl->mBridgeImpl->bridgeMamaPublisherSend (impl->mMamaPublisherBridgeImpl, msg); diff --git a/mama/c_cpp/src/c/transport.c b/mama/c_cpp/src/c/transport.c index 339dbc0..622f47d 100644 --- a/mama/c_cpp/src/c/transport.c +++ b/mama/c_cpp/src/c/transport.c @@ -25,6 +25,7 @@ #include "mama/mama.h" #include "throttle.h" +#include "plugin.h" #include "list.h" #include "transportimpl.h" #include "bridge.h" @@ -876,10 +877,22 @@ mamaTransport_create (mamaTransport transport, if ((!self->mDisableRefresh) && (!mamaTransportInternal_disableRefreshes(name))) { - return refreshTransport_create (&self->mRefreshTransport, - (mamaTransport)self, - self->mListeners, - self->mBridgeImpl); + status = refreshTransport_create (&self->mRefreshTransport, + (mamaTransport)self, + self->mListeners, + self->mBridgeImpl); + + if (MAMA_STATUS_OK != status) + return status; + } + + /* Calling plugin hook*/ + status = mamaPlugin_fireTransportPostCreateHook (transport); + if (MAMA_STATUS_OK != status) + { + mama_log (MAMA_LOG_LEVEL_ERROR, + "mamaTransport_create(): TransportPostCreateHook failed with a status of %s", + mamaStatus_stringForStatus(status)); } return MAMA_STATUS_OK; -- 1.7.1
Gary Molloy – SR Labs Adelaide Exchange | 24-26 Adelaide Street | Belfast | BT2 8GD
|
|