List:Commits« Previous MessageNext Message »
From:Magnus Blåudd Date:April 7 2010 8:43am
Subject:bzr commit into mysql-5.1-telco-7.0 branch (magnus.blaudd:3464) WL#1744
View as plain text  
#At file:///C:/mysql/7.0-EventLog/ based on revid:magnus.blaudd@stripped

 3464 Magnus Blåudd	2010-04-07
      WL#1744 NDB Windows port
       - Extend Logger with support for logging to Windows event log
       - Create a message.mc file to be used in the binaries in storage/ndb which need
         to write to the Windows event log. Compile the message file and checked in the resulting
         files to avoid having to invoke mc.exe as part of build(the message file is static).   
       - Turn on logging to Windows event log for ndb_mgmd and remove the "log to file in
          debug mode" hack.

    added:
      storage/ndb/src/common/logger/EventLogHandler.cpp
      storage/ndb/src/common/logger/EventLogHandler.hpp
      storage/ndb/src/common/logger/MSG00001.bin
      storage/ndb/src/common/logger/message.h
      storage/ndb/src/common/logger/message.mc
      storage/ndb/src/common/logger/message.rc
    modified:
      storage/ndb/include/logger/Logger.hpp
      storage/ndb/src/common/logger/CMakeLists.txt
      storage/ndb/src/common/logger/Logger.cpp
      storage/ndb/src/common/logger/Makefile.am
      storage/ndb/src/mgmsrv/CMakeLists.txt
      storage/ndb/src/mgmsrv/main.cpp
=== modified file 'storage/ndb/include/logger/Logger.hpp'
--- a/storage/ndb/include/logger/Logger.hpp	2009-12-07 12:38:38 +0000
+++ b/storage/ndb/include/logger/Logger.hpp	2010-04-07 08:43:52 +0000
@@ -144,6 +144,16 @@ public:
   void removeConsoleHandler();
 
   /**
+   * Create a default handler that logs to the Windows event log
+   * with source component set to source_name
+   *
+   * NOTE! Can only  be created on Windows.
+   *
+   * @return true if successful.
+   */
+  bool createEventLogHandler(const char* source_name);
+
+  /**
    * Create a default handler that logs to a file called logger.log.
    *
    * @return true if successful.

=== modified file 'storage/ndb/src/common/logger/CMakeLists.txt'
--- a/storage/ndb/src/common/logger/CMakeLists.txt	2008-08-20 13:22:09 +0000
+++ b/storage/ndb/src/common/logger/CMakeLists.txt	2010-04-07 08:43:52 +0000
@@ -21,4 +21,5 @@ ADD_LIBRARY(ndblogger STATIC
             LogHandlerList.cpp
             LogHandler.cpp
             ConsoleLogHandler.cpp
+            EventLogHandler.cpp
             FileLogHandler.cpp)

=== added file 'storage/ndb/src/common/logger/EventLogHandler.cpp'
--- a/storage/ndb/src/common/logger/EventLogHandler.cpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/common/logger/EventLogHandler.cpp	2010-04-07 08:43:52 +0000
@@ -0,0 +1,276 @@
+/*
+   Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+#ifdef _WIN32
+
+#include "EventLogHandler.hpp"
+#include "message.h"
+
+EventLogHandler::EventLogHandler(const char* source_name)
+ : LogHandler(),
+   m_source_name(source_name),
+   m_event_source(NULL),
+   m_level(Logger::LL_ERROR)
+{
+}
+
+
+EventLogHandler::~EventLogHandler()
+{
+  close();
+}
+
+
+static bool
+check_message_resource(void)
+{
+  // Only do check once per binary
+  static bool check_message_resource_done = false; 
+  if (check_message_resource_done)
+    return true;
+  check_message_resource_done = true;
+
+  // Each program that want to log to Windows event log need to
+  // have a message resource compiled in. Check that it's there
+  // by resolving the message from current module(.exe)
+  char* message_text;
+  if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                    FORMAT_MESSAGE_FROM_HMODULE |
+                    FORMAT_MESSAGE_IGNORE_INSERTS,
+                    NULL, MSG_EVENTLOG, NULL,
+                    (LPTSTR)&message_text, 0, NULL) != 0)
+  {
+    LocalFree(message_text);
+    return true;
+  }
+
+  // Could not get message from own module, extract error
+  // message from system and print it to help debugging
+  DWORD last_err = GetLastError();
+  fprintf(stderr,
+          "This program does not seem to have the message resource "
+          "required for logging to Windows event log, error: %u ", last_err);
+  if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+                    FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                    FORMAT_MESSAGE_IGNORE_INSERTS,
+                    NULL, last_err, 0,
+                    (LPSTR)&message_text, 0, NULL))
+  {
+    fprintf(stderr, "message: '%s'\n", message_text);
+    LocalFree(message_text);
+  }
+  else
+  {
+    fprintf(stderr, "message: <unknown>\n");
+  }
+
+  // The program have not been properly compiled, crash in debug mode 
+  assert(false);
+  return false;
+}
+
+
+static bool
+setup_eventlogging(const char* source_name)
+{
+  // Check that this binary have mesage resource compiled in
+  if (!check_message_resource())
+    return false;
+
+  char sub_key[MAX_PATH];
+  BaseString::snprintf(sub_key, sizeof(sub_key),
+    "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s",
+    source_name);
+
+  // Create the event source registry key
+  HKEY key_handle;
+  if (RegCreateKey(HKEY_LOCAL_MACHINE, sub_key, &key_handle) != ERROR_SUCCESS)
+  {
+    // Could neither create or open key
+    fprintf(stderr, "Could neither create or open key '%s', error: %u\n",
+            sub_key, GetLastError());
+    return false;
+  }
+
+  /* Get path of current module and use it as message resource  */
+  char module_path[MAX_PATH];
+  DWORD len = GetModuleFileName(NULL, module_path, sizeof(module_path));
+  if (len == 0 || len == sizeof(module_path))
+  {
+    fprintf(stderr,
+            "Could not extract path of module, module_len: %u, error: %u\n",
+            len, GetLastError());
+    RegCloseKey(key_handle);
+    return false;
+  }
+
+  (void)RegSetValueEx(key_handle, "EventMessageFile", 0, REG_EXPAND_SZ,
+                      (PBYTE)module_path, len + 1 );
+
+  /* Register supported event types */
+  const DWORD event_types= (EVENTLOG_ERROR_TYPE |
+                            EVENTLOG_WARNING_TYPE |
+                            EVENTLOG_INFORMATION_TYPE);
+  (void)RegSetValueEx(key_handle, "TypesSupported", 0, REG_DWORD,
+                      (PBYTE)&event_types, sizeof(event_types));
+
+  RegCloseKey(key_handle);
+  return true;
+}
+
+
+bool
+EventLogHandler::open()
+{
+  if (!setup_eventlogging(m_source_name))
+  {
+    fprintf(stderr, "Failed to setup event logging\n");
+    return false;
+  }
+
+  m_event_source = RegisterEventSource(NULL, m_source_name);
+  if (!m_event_source)
+  {
+    fprintf(stderr, "Failed to register event source, error: %u\n",
+            GetLastError());
+    return false;
+  }
+  return true;
+}
+
+
+bool
+EventLogHandler::close()
+{
+  if (!is_open())
+    return true;
+
+  (void)DeregisterEventSource(m_event_source);
+
+  return true;
+}
+
+
+bool
+EventLogHandler::is_open()
+{
+  return (m_event_source != NULL);
+}
+
+void 
+EventLogHandler::writeHeader(const char* pCategory, Logger::LoggerLevel level)
+{
+  m_level = level;
+}
+
+
+static bool
+write_event_log(HANDLE eventlog_handle, Logger::LoggerLevel level,
+                const char* msg)
+{
+  WORD type;
+  switch(level)
+  {
+  case Logger::LL_DEBUG:
+  case Logger::LL_INFO:
+    type = EVENTLOG_INFORMATION_TYPE;
+    break;
+
+  case Logger::LL_WARNING:
+    type = EVENTLOG_WARNING_TYPE;
+    break;
+
+  case Logger::LL_ERROR:
+  case Logger::LL_ALERT:
+  case Logger::LL_CRITICAL:
+    type = EVENTLOG_ERROR_TYPE;
+    break;
+  }
+
+  if (!ReportEvent(eventlog_handle, type, 0, MSG_EVENTLOG,
+                   NULL, 1, 0, &msg, NULL))
+  {
+    return false;
+  }
+
+  return true;
+}
+
+
+void 
+EventLogHandler::writeMessage(const char* msg)
+{
+  if (!is_open())
+    return;
+
+  if (!write_event_log(m_event_source, m_level, msg))
+  {
+    fprintf(stderr, "Failed to report event to event log, error: %u\n",
+            GetLastError());
+  }
+}
+
+
+void 
+EventLogHandler::writeFooter()
+{
+}
+
+  
+bool
+EventLogHandler::setParam(const BaseString &param, const BaseString &value) {
+  return false;
+}
+
+
+int
+EventLogHandler::printf(Logger::LoggerLevel level, const char* source_name,
+                        const char* msg, ...)
+{
+  if (setup_eventlogging(source_name))
+  {
+    // Failed to setup event logging
+    return -3;
+  }
+
+  char buf[MAX_LOG_MESSAGE_SIZE];
+  va_list ap;
+  va_start(ap, msg);
+  int ret = vsnprintf_s(buf, sizeof(buf), _TRUNCATE, msg, ap);
+  va_end(ap);
+
+  HANDLE eventlog_handle = RegisterEventSource(NULL, source_name);
+  if (!eventlog_handle)
+  {
+    // Failed to open event log 
+    return -2;
+  }
+
+  if (!write_event_log(eventlog_handle, level, buf))
+  {
+    // Failed to log, return error
+    (void)DeregisterEventSource(eventlog_handle);
+    return -1;
+  }
+
+  (void)DeregisterEventSource(eventlog_handle);
+
+  // Ok, return length of the logged message
+  return ret;
+}
+
+#endif
\ No newline at end of file

=== added file 'storage/ndb/src/common/logger/EventLogHandler.hpp'
--- a/storage/ndb/src/common/logger/EventLogHandler.hpp	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/common/logger/EventLogHandler.hpp	2010-04-07 08:43:52 +0000
@@ -0,0 +1,63 @@
+/*
+   Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+*/
+
+#ifndef EVENTLOGHANDLER_H
+#define EVENTLOGHANDLER_H
+
+#include "LogHandler.hpp"
+
+/**
+ * Log messages to the Windows event log
+ *
+ * Example:
+ *  // To make everything written to g_eventLogger also
+ *   // end up in Windows event log
+ *  g_eventLogger->createEventLoghandler("MySQL Cluster Management Server");
+ *
+ * // To log a message(normally an error) before g_eventLogger has been created
+ * EventLogHandler::printf(LL_ERROR, "MySQL Cluster Management Server",
+ *                         "Failed to create shutdown event, error: %d", err); 
+ */
+class EventLogHandler : public LogHandler
+{
+public:
+  EventLogHandler(const char* source_name);
+  virtual ~EventLogHandler();
+
+  virtual bool open();
+  virtual bool close();
+  virtual bool is_open();
+
+  virtual bool setParam(const BaseString &param, const BaseString &value);
+
+  // Write message to event log without an open EventLogHandler
+  static int printf(Logger::LoggerLevel m_level, const char* source_name,
+                    const char* msg, ...) ATTRIBUTE_FORMAT(printf, 3, 4);
+private:
+  virtual void writeHeader(const char* pCategory, Logger::LoggerLevel level);
+  virtual void writeMessage(const char* pMsg);
+  virtual void writeFooter();
+
+  EventLogHandler(const EventLogHandler&); // Not impl.
+  EventLogHandler operator = (const EventLogHandler&); // Not impl.
+  bool operator == (const EventLogHandler&); // Not impl.
+
+  const char* m_source_name;
+  HANDLE m_event_source;
+  Logger::LoggerLevel m_level;
+};
+#endif

=== modified file 'storage/ndb/src/common/logger/Logger.cpp'
--- a/storage/ndb/src/common/logger/Logger.cpp	2009-12-07 12:38:38 +0000
+++ b/storage/ndb/src/common/logger/Logger.cpp	2010-04-07 08:43:52 +0000
@@ -25,7 +25,9 @@
 #include <FileLogHandler.hpp>
 #include "LogHandlerList.hpp"
 
-#if !defined NDB_WIN32
+#ifdef _WIN32
+#include "EventLogHandler.hpp"
+#else
 #include <SysLogHandler.hpp>
 #endif
 
@@ -101,6 +103,27 @@ Logger::removeConsoleHandler()
 }
 
 bool
+Logger::createEventLogHandler(const char* source_name)
+{
+#ifdef _WIN32
+  Guard g(m_handler_mutex);
+
+  LogHandler* log_handler = new EventLogHandler(source_name);
+  if (!log_handler)
+    return false;
+
+  if (!addHandler(log_handler))
+  {
+    delete log_handler;
+    return false;
+  }
+  return true;
+#else
+  return false;
+#endif
+}
+
+bool
 Logger::createFileHandler(char*filename)
 {
   Guard g(m_handler_mutex);
@@ -133,15 +156,14 @@ Logger::removeFileHandler()
 bool
 Logger::createSyslogHandler()
 {
+#ifdef _WIN32
+  return false;
+#else
   Guard g(m_handler_mutex);
   bool rc = true;
   if (m_pSyslogHandler == NULL)
   {
-#if defined NDB_WIN32
-    m_pSyslogHandler = new ConsoleLogHandler(); 
-#else
     m_pSyslogHandler = new SysLogHandler(); 
-#endif
     if (!addHandler(m_pSyslogHandler)) // TODO: check error code
     {
       rc = false;
@@ -151,6 +173,7 @@ Logger::createSyslogHandler()
   }
 
   return rc;
+#endif
 }
 
 void 
@@ -204,7 +227,7 @@ Logger::addHandler(const BaseString &log
 
     LogHandler *handler = NULL;
 
-#ifndef NDB_WIN32
+#ifndef _WIN32
     if(type == "SYSLOG")
     {
       handler = new SysLogHandler();

=== added file 'storage/ndb/src/common/logger/MSG00001.bin'
Files a/storage/ndb/src/common/logger/MSG00001.bin	1970-01-01 00:00:00 +0000 and b/storage/ndb/src/common/logger/MSG00001.bin	2010-04-07 08:43:52 +0000 differ

=== modified file 'storage/ndb/src/common/logger/Makefile.am'
--- a/storage/ndb/src/common/logger/Makefile.am	2009-05-27 15:21:45 +0000
+++ b/storage/ndb/src/common/logger/Makefile.am	2010-04-07 08:43:52 +0000
@@ -14,16 +14,16 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
 
-EXTRA_DIST = CMakeLists.txt
+EXTRA_DIST = CMakeLists.txt \
+  message.mc message.h message.rc MSG00001.bin
 
 noinst_LTLIBRARIES = liblogger.la
 
-SOURCE_WIN = Logger.cpp LogHandlerList.cpp LogHandler.cpp \
-           ConsoleLogHandler.cpp FileLogHandler.cpp
-liblogger_la_SOURCES = $(SOURCE_WIN) SysLogHandler.cpp
+liblogger_la_SOURCES = Logger.cpp \
+  LogHandlerList.cpp LogHandler.cpp \
+  ConsoleLogHandler.cpp FileLogHandler.cpp \
+  SysLogHandler.cpp EventLoghandler.cpp
 
 include $(top_srcdir)/storage/ndb/config/common.mk.am
 include $(top_srcdir)/storage/ndb/config/type_ndbapi.mk.am
 
-# Don't update the files from bitkeeper
-%::SCCS/s.%

=== added file 'storage/ndb/src/common/logger/message.h'
--- a/storage/ndb/src/common/logger/message.h	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/common/logger/message.h	2010-04-07 08:43:52 +0000
@@ -0,0 +1,56 @@
+/*
+  To change or add messages ndbd or ndb_mgmd writes to the Windows
+  error log, run
+   mc.exe message.mc
+  and checkin generated messages.h, messages.rc and msg000001.bin under the 
+  source control.
+  mc.exe can be installed with Windows SDK, some Visual Studio distributions 
+  do not include it.
+*/
+//
+//  Values are 32 bit values laid out as follows:
+//
+//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
+//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+//  +---+-+-+-----------------------+-------------------------------+
+//  |Sev|C|R|     Facility          |               Code            |
+//  +---+-+-+-----------------------+-------------------------------+
+//
+//  where
+//
+//      Sev - is the severity code
+//
+//          00 - Success
+//          01 - Informational
+//          10 - Warning
+//          11 - Error
+//
+//      C - is the Customer code flag
+//
+//      R - is a reserved bit
+//
+//      Facility - is the facility code
+//
+//      Code - is the facility's status code
+//
+//
+// Define the facility codes
+//
+
+
+//
+// Define the severity codes
+//
+
+
+//
+// MessageId: MSG_EVENTLOG
+//
+// MessageText:
+//
+// %1.
+// 
+// 
+//
+#define MSG_EVENTLOG                     0xC0000064L
+

=== added file 'storage/ndb/src/common/logger/message.mc'
--- a/storage/ndb/src/common/logger/message.mc	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/common/logger/message.mc	2010-04-07 08:43:52 +0000
@@ -0,0 +1,17 @@
+;/*
+;  To change or add messages ndbd or ndb_mgmd writes to the Windows
+;  error log, run
+;   mc.exe message.mc
+;  and checkin generated messages.h, messages.rc and msg000001.bin under the 
+;  source control.
+;  mc.exe can be installed with Windows SDK, some Visual Studio distributions 
+;  do not include it.
+;*/
+MessageId    = 100
+Severity     = Error
+Facility     = Application
+SymbolicName = MSG_EVENTLOG
+Language     = English
+%1.
+
+

=== added file 'storage/ndb/src/common/logger/message.rc'
--- a/storage/ndb/src/common/logger/message.rc	1970-01-01 00:00:00 +0000
+++ b/storage/ndb/src/common/logger/message.rc	2010-04-07 08:43:52 +0000
@@ -0,0 +1,2 @@
+LANGUAGE 0x9,0x1
+1 11 "MSG00001.bin"

=== modified file 'storage/ndb/src/mgmsrv/CMakeLists.txt'
--- a/storage/ndb/src/mgmsrv/CMakeLists.txt	2010-03-05 19:19:56 +0000
+++ b/storage/ndb/src/mgmsrv/CMakeLists.txt	2010-04-07 08:43:52 +0000
@@ -29,6 +29,8 @@ ADD_LIBRARY(ndbconf
 )
 
 ADD_EXECUTABLE(ndb_mgmd
+               ${CMAKE_SOURCE_DIR}/storage/ndb/src/common/logger/message.rc
+               ${CMAKE_SOURCE_DIR}/storage/ndb/src/common/logger/msg00001.bin
                MgmtSrvr.cpp
                main.cpp
                Services.cpp

=== modified file 'storage/ndb/src/mgmsrv/main.cpp'
--- a/storage/ndb/src/mgmsrv/main.cpp	2009-11-13 11:24:05 +0000
+++ b/storage/ndb/src/mgmsrv/main.cpp	2010-04-07 08:43:52 +0000
@@ -202,21 +202,14 @@ static int mgmd_main(int argc, char** ar
 
   g_eventLogger->setCategory(opt_logname);
 
-#ifdef _WIN32
-#ifdef _DEBUG
-  if (opts.daemon)
-  {
-    /* Write eventlog output to file for easier debugging */
-    g_eventLogger->createFileHandler("c:\\ndb_mgmd_debug.log");
-    g_eventLogger->info("StdoutFileName: %s", NdbConfig_StdoutFileName(0));
-    g_eventLogger->info("get_path: %s", NdbConfig_get_path(0));
-    g_eventLogger->info("GetCommandLine: %s", GetCommandLine());
-  }
-#endif
-#endif
   /* Output to console initially */
   g_eventLogger->createConsoleHandler();
 
+#ifdef _WIN32
+  /* Output to Windows event log */
+  g_eventLogger->createEventLogHandler("MySQL Cluster Management Server");
+#endif
+
   if (opts.verbose)
     g_eventLogger->enable(Logger::LL_DEBUG);
 

Attachment: [text/bzr-bundle] bzr/magnus.blaudd@sun.com-20100407084352-bw9a24h55nfek2wp.bundle
Thread
bzr commit into mysql-5.1-telco-7.0 branch (magnus.blaudd:3464) WL#1744Magnus Blåudd7 Apr