[PATCH 1/3] [MAMAC] mamaPlugin Feature


Gary Molloy <g.molloy@...>
 

Testing Strategy:-

Not middleware or O/S specific. 
 

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

g.molloy@...

 


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:-

Not middleware or O/S specific. 
 

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

g.molloy@...