Classes Files

cs/MAMA.cs

Namespaces

Name
Wombat
System::Collections::Generic
System::IO
System::Runtime::InteropServices
System::Threading

Classes

  Name
class Wombat::Mama
MAMA - Middleware Agnostic Messaging API

Source code

/* $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
 */

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;

namespace Wombat
{
    #region Public Enumerations

    public enum MamaLogLevel
    {
        MAMA_LOG_LEVEL_OFF = 0,
        MAMA_LOG_LEVEL_SEVERE = 1,
        MAMA_LOG_LEVEL_ERROR = 2,
        MAMA_LOG_LEVEL_WARN = 3,
        MAMA_LOG_LEVEL_NORMAL = 4,
        MAMA_LOG_LEVEL_FINE   = 5,
        MAMA_LOG_LEVEL_FINER  = 6,
        MAMA_LOG_LEVEL_FINEST = 7
    }

    public enum MamaLogFilePolicy
    {
        LOGFILE_UNBOUNDED = 1,
        LOGFILE_ROLL = 2,
        LOGFILE_OVERWRITE = 3,
        LOGFILE_USER = 4
    }

    #endregion

    public class Mama
    {
        /* ************************************************************** */
        #region Class Member Definition

        /* ************************************************************** */
        #region Internal Delegates

        internal delegate void LogFileCallbackDelegate(
            int level,
            [MarshalAs(UnmanagedType.LPStr)]
                string message);

        internal delegate void LogSizeCallbackDelegate();

        #endregion

        /* ************************************************************** */
        #region Private Member Variables


        private static MamaCallbackWrapper<MamaLogFileCallback2, LogFileCallbackDelegate> m_logFileCbWrapper;

        private static MamaCallbackWrapper<MamaLogFileCallback, LogSizeCallbackDelegate> m_logSizeCbWrapper;

        #endregion

        #endregion

        public static MamaLogLevel GetLogLevelForString(string level)
        {
            if (level.Equals("OFF", StringComparison.OrdinalIgnoreCase))
            {
                return MamaLogLevel.MAMA_LOG_LEVEL_OFF;
            }
            if (level.Equals("SEVERE", StringComparison.OrdinalIgnoreCase))
            {
                return MamaLogLevel.MAMA_LOG_LEVEL_SEVERE;
            }
            if (level.Equals("ERROR", StringComparison.OrdinalIgnoreCase))
            {
                return MamaLogLevel.MAMA_LOG_LEVEL_ERROR;
            }
            if (level.Equals("WARN", StringComparison.OrdinalIgnoreCase))
            {
                return MamaLogLevel.MAMA_LOG_LEVEL_WARN;
            }
            if (level.Equals("NORMAL", StringComparison.OrdinalIgnoreCase))
            {
                return MamaLogLevel.MAMA_LOG_LEVEL_NORMAL;
            }
            if (level.Equals("FINE", StringComparison.OrdinalIgnoreCase))
            {
                return MamaLogLevel.MAMA_LOG_LEVEL_FINE;
            }
            if (level.Equals("FINER", StringComparison.OrdinalIgnoreCase))
            {
                return MamaLogLevel.MAMA_LOG_LEVEL_FINER;
            }
            if (level.Equals("FINEST", StringComparison.OrdinalIgnoreCase))
            {
                return MamaLogLevel.MAMA_LOG_LEVEL_FINEST;
            }

            return MamaLogLevel.MAMA_LOG_LEVEL_NORMAL;
        }

        public static void setLogCallback(MamaLogFileCallback2 callback)
        {
            // Dispose the old callback wrapper
            if (m_logFileCbWrapper != null)
            {
                ((IDisposable)m_logFileCbWrapper).Dispose();
                m_logFileCbWrapper = null;
            }

            // Null is allowed to clear the callback
            if (callback == null)
            {
                // Call the native function with null
                MamaWrapper.CheckResultCode(NativeMethods.mama_setLogCallback2(null));
            }

            else
            {
                // Create a new callback wrapper
                m_logFileCbWrapper = new MamaCallbackWrapper<MamaLogFileCallback2, LogFileCallbackDelegate>(
                        callback,
                        null,
                        new LogFileCallbackDelegate(onNativeLogCallback));

                // Call the native function
                MamaWrapper.CheckResultCode(NativeMethods.mama_setLogCallback2((LogFileCallbackDelegate)m_logFileCbWrapper.NativeDelegate));
            }
        }

        public static void setLogSizeCb(MamaLogFileCallback callback)
        {
            // Dispose the old callback wrapper
            if (m_logSizeCbWrapper != null)
            {
                ((IDisposable)m_logSizeCbWrapper).Dispose();
                m_logSizeCbWrapper = null;
            }

            // Null is allowed to clear the callback
            if (callback == null)
            {
                // Call the native function with null
                MamaWrapper.CheckResultCode(NativeMethods.mama_setLogSizeCb(null));
            }

            else
            {
                // Create a new callback wrapper
                m_logSizeCbWrapper = new MamaCallbackWrapper<MamaLogFileCallback, LogSizeCallbackDelegate>(
                        callback,
                        null,
                        new LogSizeCallbackDelegate(onNativeLogSizeExceeded));

                // Call the native function
                MamaWrapper.CheckResultCode(NativeMethods.mama_setLogSizeCb((LogSizeCallbackDelegate)m_logSizeCbWrapper.NativeDelegate));
            }
        }

        public static void onNativeLogCallback(int level, string message)
        {
            // Get the callback from the static member variable
            MamaLogFileCallback2 callback = (MamaLogFileCallback2)m_logFileCbWrapper.Callback;
            if (callback != null)
            {
                // Invoke the delegate
                callback.onLog((MamaLogLevel)level, message);
            }
        }

        private static void onNativeLogSizeExceeded()
        {
            // Get the callback from the static member variable
            MamaLogFileCallback callback = (MamaLogFileCallback)m_logSizeCbWrapper.Callback;
            if (callback != null)
            {
                // Invoke the delegate
                callback.onLogSizeExceeded();
            }
        }

#if _GNU
        public const string DllName = "mama";
#elif _OSX
        public const string DllName = "mama";
#elif DEBUG
        public const string DllName = "libmamacmdd.dll";
#else
        public const string DllName = "libmamacmd.dll";
#endif

        public static MamaBridge loadBridge (string middleware)
        {
            return new MamaBridge (middleware);
        }


        public static MamaBridge loadBridge (string middleware, string path)
        {
            return new MamaBridge (middleware, path);
        }

        public static MamaPayloadBridge loadPayloadBridge (string payload)
        {
            return new MamaPayloadBridge (payload);
        }

        public static void open ()
        {
            initGetVersionWrapper();
            MamaWrapper.CheckResultCode(NativeMethods.mama_open());
            Interlocked.Increment(ref mMamaopen);
        }

        public static void openWithProperties (string path, string filename)
        {
            initGetVersionWrapper();
            MamaWrapper.CheckResultCode (NativeMethods.mama_openWithProperties (path, filename));
            Interlocked.Increment(ref mMamaopen);
        }

        public static void setProperty (string name, string value)
        {
            MamaWrapper.CheckResultCode (NativeMethods.mama_setProperty (name, value));
        }

        public static string getProperty (string name)
        {
            return Marshal.PtrToStringAnsi(NativeMethods.mama_getProperty (name));
        }

        public static void loadDefaultProperties ()
        {
            NativeMethods.mama_loadDefaultProperties ();
        }

        public static string getProperty (string name, string defaultValue)
        {
            string property = getProperty(name);
            if (null == property)
            {
                return defaultValue;
            }
            else
            {
                return property;
            }
        }

        public static Dictionary<string, string> getProperties ()
        {
            IntPtr propertiesAsStringPtr = NativeMethods.mama_getPropertiesAsString();
            string propertiesAsString = Marshal.PtrToStringAnsi(propertiesAsStringPtr);
            // We have our C# string now - free underlying native memory
            NativeMethods.mama_freeAllocatedBuffer(propertiesAsStringPtr);

            Dictionary<string, string> result = new Dictionary<string, string>();
            if (null == propertiesAsString)
            {
                return result;
            }
            string[] propPairs = propertiesAsString.Split('\n');
            foreach (string propStringPair in propPairs) {
                String[] pair = propStringPair.Split('=');
                if (pair.Length > 1) {
                    result.Add(pair[0], pair[1]);
                }
            }
            return result;
        }

        public static string getVersion (MamaBridge bridgeImpl)
        {
            return MamaVersion.MAMADOTNET_VERSION + " (" + Marshal.PtrToStringAnsi(NativeMethods.mama_getVersion (bridgeImpl.NativeHandle)) + ")";
        }

        private static string getVersion (IntPtr bridgeImpl)
        {
            return MamaVersion.MAMADOTNET_VERSION + " (" + Marshal.PtrToStringAnsi(NativeMethods.mama_getVersion (bridgeImpl)) + ")";
        }

        public static void start(MamaBridge bridgeImpl)
        {
            MamaWrapper.CheckResultCode(NativeMethods.mama_start(bridgeImpl.NativeHandle));
        }

        public static void startAll()
        {
            MamaWrapper.CheckResultCode(NativeMethods.mama_startAll(true));
        }

        public static void startAll(bool isBlocking)
        {
            MamaWrapper.CheckResultCode(NativeMethods.mama_startAll(isBlocking));
        }

        public static void stopAll()
        {
            MamaWrapper.CheckResultCode(NativeMethods.mama_stopAll());
        }
        
        public static void close ()
        {
            try
            {
                MamaWrapper.CheckResultCode(NativeMethods.mama_close());
            }

            finally
            {
                /* Decrement the ref count even if something went wrong or there will be crashes
                 * when the various objects are finalized.
                 * The objects will only destroy the native objects if MAMA is still open.
                 */
                Interlocked.Decrement(ref mMamaopen);
            }
        }

        public static void startBackground(MamaBridge bridgeImpl, MamaStartBackgroundCallback callback)
        {
            // Allocate a fowarder object
            mStartBackgroundCallbackForwarder = new StartBackgroundCallbackForwarder(callback);
            mStartBackgroundShimCallback = new StartBackgroundCallbackForwarder.StartBackgroundCompleteDelegate(mStartBackgroundCallbackForwarder.onStartBackgroundCompleted);

            // Call the native function
            MamaWrapper.CheckResultCode(NativeMethods.mama_startBackground(bridgeImpl.NativeHandle, mStartBackgroundShimCallback));
        }


        public static bool opened
        {
            get
            {
                return (mMamaopen > 0);
            }
        }

        public static void stop (MamaBridge bridgeImpl)
        {
            MamaWrapper.CheckResultCode(NativeMethods.mama_stop(bridgeImpl.NativeHandle));
        }

        public static void enableLogging (MamaLogLevel level)
        {
            // Check for a valid enumeration value
            if (!Enum.IsDefined(typeof(MamaLogLevel), (int)level))
            {
                throw new ArgumentOutOfRangeException("level");
            }
            MamaWrapper.CheckResultCode(NativeMethods.mama_enableLogging(IntPtr.Zero, (int)level));
        }

        public static void logToFile(string fileName, MamaLogLevel level)
        {
            // Check the arguments
            if ((fileName == null) || (fileName == string.Empty))
            {
                throw new ArgumentNullException("fileName");
            }

            // Check for invalid characters in the file name
            if (fileName.IndexOfAny(Path.GetInvalidPathChars()) != -1)
            {
                throw new ArgumentOutOfRangeException(fileName, "The file or path contains invalid characters");
            }

            // Check for a valid enumeration value
            if (!Enum.IsDefined(typeof(MamaLogLevel), (int)level))
            {
                throw new ArgumentOutOfRangeException("level");
            }

            // Call the native function
            MamaWrapper.CheckResultCode(NativeMethods.mama_logToFile(fileName, (int)level));
        }

        public static void disableLogging()
        {
            MamaWrapper.CheckResultCode(NativeMethods.mama_disableLogging());
        }

        public static void logDestroy()
        {
            NativeMethods.mama_logDestroy();
        }

        public static void setLogLevel(MamaLogLevel level)
        {
            // Check for a valid enumeration value
            if (!Enum.IsDefined(typeof(MamaLogLevel), (int)level))
            {
                throw new ArgumentOutOfRangeException("level");
            }

            MamaWrapper.CheckResultCode(NativeMethods.mama_setLogLevel((int)level));
        }

        public static MamaLogLevel getLogLevel()
        {
            return (MamaLogLevel)NativeMethods.mama_getLogLevel();
        }

        public static void setLogSize(ulong size)
        {
            // Check the argument
            if (size == 0)
            {
                throw new ArgumentOutOfRangeException("size");
            }

            MamaWrapper.CheckResultCode(NativeMethods.mama_setLogSize(size));
        }

        public static void setNumLogFiles(int numFiles)
        {
            // Check the argument
            if (numFiles < 1)
            {
                throw new ArgumentOutOfRangeException("numFiles");
            }

            MamaWrapper.CheckResultCode(NativeMethods.mama_setNumLogFiles(numFiles));
        }

        public static void setLogFilePolicy(MamaLogFilePolicy policy)
        {
            MamaWrapper.CheckResultCode(NativeMethods.mama_setLogFilePolicy((int)policy));
        }

        public static void setAppendToLogFile(bool append)
        {
            int appendC = 0;
            if(append)
                appendC = 1;

            MamaWrapper.CheckResultCode(NativeMethods.mama_setAppendToLogFile(appendC));
        }

        public static bool loggingToFile()
        {
            int loggingToFile = NativeMethods.mama_loggingToFile();
            if(0 == loggingToFile)
                return false;
            else
                return true;
        }

        public static void log(MamaLogLevel level, string text)
        {
            // Check for a valid enumeration value
            if (!Enum.IsDefined(typeof(MamaLogLevel), (int)level))
            {
                throw new ArgumentOutOfRangeException("level");
            }

            // If null has been passed for the text then use a blank string
            if (text == null)
            {
                NativeMethods.mama_log2((int)level, string.Empty);
            }

            else
            {
                NativeMethods.mama_log2((int)level, text);
            }
        }

        public static void defaultLogFunction(MamaLogLevel level, string text)
        {
            // Check the arguments
            if ((text == null) || (text == string.Empty))
            {
                throw new ArgumentNullException("text");
            }

            // Check for a valid enumeration value
            if (!Enum.IsDefined(typeof(MamaLogLevel), (int)level))
            {
                throw new ArgumentOutOfRangeException("level");
            }

            // Call the native method
            NativeMethods.mama_logDefault2((int)level, text);
        }



        public static void setDefaultQueueHighWatermark (int highWatermark)
        {

        }

        public static void setDefaultQueueLowWatermark (int lowWatermark)
        {

        }

        public static MamaQueue getDefaultEventQueue (MamaBridge bridgeImpl)
        {
            IntPtr queuePtr = IntPtr.Zero;
            int code = NativeMethods.mama_getDefaultEventQueue (bridgeImpl.NativeHandle, ref queuePtr);
            MamaWrapper.CheckResultCode(code);
            return new MamaQueue (queuePtr);
        }

        #region Implementation details


        // For WAM, allows the C-layer to call up to the wrapper so we can get
        // the wrapper version in addition to the C version
        private delegate string wrapperGetVersion(IntPtr bridgeImpl);
        private static wrapperGetVersion wrapperVersionGetter = new wrapperGetVersion(getVersion);
        private static void initGetVersionWrapper()
        {
            NativeMethods.mama_setWrapperGetVersion(wrapperVersionGetter);
        }

        private class StartBackgroundCallbackForwarder
        {
            private MamaStartBackgroundCallback mCallback;

            public delegate void StartBackgroundCompleteDelegate(MamaStatus.mamaStatus status);

            public StartBackgroundCallbackForwarder(MamaStartBackgroundCallback callback)
            {
                // Save arguments in member variables
                mCallback = callback;
            }

            internal void onStartBackgroundCompleted(MamaStatus.mamaStatus status)
            {
                // Invoke the callback function
                if (mCallback != null)
                {
                    // Create a new mama status using the data passed in
                    mCallback.onStartComplete(status);
                }
            }

        }

        // Interop API
        private struct NativeMethods
        {
            // export definitions
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_open();
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_openWithProperties(string path, string filename);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_setProperty (string name, string value);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern IntPtr mama_getProperty (string name);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern void mama_loadDefaultProperties ();
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern IntPtr mama_getPropertiesAsString ();
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern void mama_freeAllocatedBuffer (IntPtr buffer);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern IntPtr mama_getVersion (IntPtr bridgeImpl);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_close();
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_start (IntPtr bridgeImpl);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_startAll(bool isBlocking);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_startBackground(IntPtr bridgeImpl, StartBackgroundCallbackForwarder.StartBackgroundCompleteDelegate callback);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_stop (IntPtr bridgeImpl);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_stopAll();
            [DllImport(DllName, CallingConvention=CallingConvention.Cdecl)]
            public static extern int mama_enableLogging (IntPtr f, int level);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_logToFile(string fileName, int level);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_disableLogging();
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern void mama_logDestroy();
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_setLogLevel(int level);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_getLogLevel();
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_setLogSize(ulong size);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_setNumLogFiles(int numFiles);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_setLogFilePolicy(int policy);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_setAppendToLogFile(int append);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_loggingToFile();
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_setLogSizeCb(LogSizeCallbackDelegate callback);
            [DllImport(DllName, CallingConvention = CallingConvention.StdCall)]
            public static extern void mama_log2(int level, string txt);
            [DllImport(DllName, CallingConvention = CallingConvention.StdCall)]
            public static extern void mama_logDefault2(int level, string txt);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern void mama_setWrapperGetVersion(wrapperGetVersion getVer);
            [DllImport(DllName, CallingConvention=CallingConvention.Cdecl)]
            public static extern int mama_getDefaultEventQueue (IntPtr bridgeImpl, ref IntPtr queuePtr);
            [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
            public static extern int mama_setLogCallback2(LogFileCallbackDelegate callback);
        }

        // Static variables used to dispatch callback events from mama_startbackground.
        private static StartBackgroundCallbackForwarder mStartBackgroundCallbackForwarder;
        private static StartBackgroundCallbackForwarder.StartBackgroundCompleteDelegate mStartBackgroundShimCallback;

        private static int mMamaopen = 0;

#endregion // Implementation details
    }
}

Updated on 2023-03-31 at 15:29:33 +0100