Drizzled Public API Documentation

error_message.cc
00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 
00020 #include <config.h>
00021 
00022 #include <drizzled/error.h>
00023 #include <drizzled/gettext.h>
00024 #include <drizzled/plugin/error_message.h>
00025 
00026 #include <cstdio>
00027 #include <algorithm>
00028 #include <vector>
00029 
00030 namespace drizzled
00031 {
00032 
00033 std::vector<plugin::ErrorMessage *> all_errmsg_handler;
00034 
00035 bool plugin::ErrorMessage::addPlugin(plugin::ErrorMessage *handler)
00036 {
00037   all_errmsg_handler.push_back(handler);
00038   return false;
00039 }
00040 
00041 void plugin::ErrorMessage::removePlugin(plugin::ErrorMessage *)
00042 {
00043   all_errmsg_handler.clear();
00044 }
00045 
00046 
00047 class Print : public std::unary_function<plugin::ErrorMessage *, bool>
00048 {
00049   error::level_t priority;
00050   const char *format;
00051   va_list ap;
00052 
00053 public:
00054   Print(error::level_t priority_arg,
00055         const char *format_arg, va_list ap_arg) : 
00056     std::unary_function<plugin::ErrorMessage *, bool>(),
00057     priority(priority_arg), format(format_arg)
00058   {
00059     va_copy(ap, ap_arg);
00060   }
00061 
00062   ~Print()  { va_end(ap); }
00063 
00064   inline result_type operator()(argument_type handler)
00065   {
00066     va_list handler_ap;
00067     va_copy(handler_ap, ap);
00068     if (handler->errmsg(priority, format, handler_ap))
00069     {
00070       /* we're doing the errmsg plugin api,
00071          so we can't trust the errmsg api to emit our error messages
00072          so we will emit error messages to stderr */
00073       /* TRANSLATORS: The leading word "errmsg" is the name
00074          of the plugin api, and so should not be translated. */
00075       fprintf(stderr,
00076               _("errmsg plugin '%s' errmsg() failed"),
00077               handler->getName().c_str());
00078       va_end(handler_ap);
00079       return true;
00080     }
00081     va_end(handler_ap);
00082     return false;
00083   }
00084 }; 
00085 
00086 
00087 bool plugin::ErrorMessage::vprintf(error::level_t priority, char const *format, va_list ap)
00088 {
00089   if (not (priority >= error::verbosity()))
00090     return false;
00091 
00092   /* 
00093     Check to see if any errmsg plugin has been loaded
00094     if not, just fall back to emitting the message to stderr.
00095   */
00096   if (not all_errmsg_handler.size())
00097   {
00098     /* if it turns out that the vfprintf doesnt do one single write
00099        (single writes are atomic), then this needs to be rewritten to
00100        vsprintf into a char buffer, and then write() that char buffer
00101        to stderr */
00102       vfprintf(stderr, format, ap);
00103       fputc('\n', stderr);
00104     return false;
00105   }
00106 
00107   /* Use find_if instead of foreach so that we can collect return codes */
00108   std::vector<plugin::ErrorMessage *>::iterator iter=
00109     std::find_if(all_errmsg_handler.begin(), all_errmsg_handler.end(),
00110                  Print(priority, format, ap)); 
00111 
00112   /* If iter is == end() here, that means that all of the plugins returned
00113    * false, which in this case means they all succeeded. Since we want to 
00114    * return false on success, we return the value of the two being != 
00115    */
00116   return iter != all_errmsg_handler.end();
00117 }
00118 
00119 } /* namespace drizzled */