summaryrefslogtreecommitdiffstats
path: root/src/Daemon/CrashWatcher.cpp
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-08-21 17:08:46 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-08-21 17:08:46 +0200
commit60a0355316954c96febd7bcd46862a4145a800cd (patch)
tree5463c1a2d11785b070df1ce943f24a937961595a /src/Daemon/CrashWatcher.cpp
parent41942e23c9cdcb9388041a7ef2885a46074744e7 (diff)
downloadabrt-60a0355316954c96febd7bcd46862a4145a800cd.tar.gz
abrt-60a0355316954c96febd7bcd46862a4145a800cd.tar.xz
abrt-60a0355316954c96febd7bcd46862a4145a800cd.zip
at Jirka's request, restore setup where CCrashWatcher has its own source files
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'src/Daemon/CrashWatcher.cpp')
-rw-r--r--src/Daemon/CrashWatcher.cpp399
1 files changed, 399 insertions, 0 deletions
diff --git a/src/Daemon/CrashWatcher.cpp b/src/Daemon/CrashWatcher.cpp
new file mode 100644
index 00000000..750d32a6
--- /dev/null
+++ b/src/Daemon/CrashWatcher.cpp
@@ -0,0 +1,399 @@
+/*
+ Copyright (C) 2009 Jiri Moskovcak (jmoskovc@redhat.com)
+ Copyright (C) 2009 RedHat inc.
+
+ 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include "abrtlib.h"
+#include "CrashWatcher.h"
+#include <iostream>
+#include <sstream>
+#include "ABRTException.h"
+
+void CCrashWatcher::Status(const std::string& pMessage, const std::string& pDest)
+{
+ std::cout << "Update: " + pMessage << std::endl;
+ //FIXME: send updates only to job owner
+ if(m_pCommLayer != NULL)
+ m_pCommLayer->Update(pDest,pMessage);
+}
+
+void CCrashWatcher::Warning(const std::string& pMessage, const std::string& pDest)
+{
+ std::cerr << "Warning: " + pMessage << std::endl;
+ if(m_pCommLayer != NULL)
+ m_pCommLayer->Warning(pDest,pMessage);
+}
+
+void CCrashWatcher::Debug(const std::string& pMessage, const std::string& pDest)
+{
+ //some logic to add logging levels?
+ std::cout << "Debug: " + pMessage << std::endl;
+}
+
+CCrashWatcher::CCrashWatcher(const std::string& pPath)
+{
+ g_cw = this;
+
+ int watch = 0;
+ m_sTarget = pPath;
+
+ // TODO: initialize object according parameters -w -d
+ // status has to be always created.
+ m_pCommLayer = NULL;
+ comm_layer_inner_init(this);
+
+ m_pSettings = new CSettings();
+ m_pSettings->LoadSettings(std::string(CONF_DIR) + "/abrt.conf");
+
+ m_pMainloop = g_main_loop_new(NULL,FALSE);
+ m_pMW = new CMiddleWare(PLUGINS_CONF_DIR,PLUGINS_LIB_DIR);
+ if (pthread_mutex_init(&m_pJobsMutex, NULL) != 0)
+ {
+ throw CABRTException(EXCEP_FATAL, "CCrashWatcher::CCrashWatcher(): Can't init mutex!");
+ }
+ try
+ {
+ SetUpMW();
+ SetUpCron();
+ FindNewDumps(pPath);
+#ifdef ENABLE_DBUS
+ m_pCommLayer = new CCommLayerServerDBus();
+#elif ENABLE_SOCKET
+ m_pCommLayer = new CCommLayerServerSocket();
+#endif
+// m_pCommLayer = new CCommLayerServerDBus();
+// m_pCommLayer = new CCommLayerServerSocket();
+ m_pCommLayer->Attach(this);
+
+ if ((m_nFd = inotify_init()) == -1)
+ {
+ throw CABRTException(EXCEP_FATAL, "CCrashWatcher::CCrashWatcher(): Init Failed");
+ }
+ if ((watch = inotify_add_watch(m_nFd, pPath.c_str(), IN_CREATE)) == -1)
+ {
+ throw CABRTException(EXCEP_FATAL, "CCrashWatcher::CCrashWatcher(): Add watch failed:" + pPath);
+ }
+ m_pGio = g_io_channel_unix_new(m_nFd);
+ }
+ catch (...)
+ {
+ /* This restores /proc/sys/kernel/core_pattern, among other things */
+ delete m_pMW;
+ //too? delete m_pCommLayer;
+ throw;
+ }
+}
+
+CCrashWatcher::~CCrashWatcher()
+{
+ //delete dispatcher, connection, etc..
+ //m_pConn->disconnect();
+
+ g_io_channel_unref(m_pGio);
+ g_main_loop_unref(m_pMainloop);
+
+ delete m_pCommLayer;
+ delete m_pMW;
+ delete m_pSettings;
+ if (pthread_mutex_destroy(&m_pJobsMutex) != 0)
+ {
+ throw CABRTException(EXCEP_FATAL, "CCrashWatcher::CCrashWatcher(): Can't destroy mutex!");
+ }
+ /* delete pid file */
+ unlink(VAR_RUN_PIDFILE);
+ /* delete lock file */
+ unlink(VAR_RUN_LOCK_FILE);
+}
+
+vector_crash_infos_t CCrashWatcher::GetCrashInfos(const std::string &pUID)
+{
+ vector_crash_infos_t retval;
+ Debug("Getting crash infos...");
+ try
+ {
+ vector_pair_string_string_t UUIDsUIDs;
+ UUIDsUIDs = m_pMW->GetUUIDsOfCrash(pUID);
+
+ unsigned int ii;
+ for (ii = 0; ii < UUIDsUIDs.size(); ii++)
+ {
+ CMiddleWare::mw_result_t res;
+ map_crash_info_t info;
+
+ res = m_pMW->GetCrashInfo(UUIDsUIDs[ii].first, UUIDsUIDs[ii].second, info);
+ switch (res)
+ {
+ case CMiddleWare::MW_OK:
+ retval.push_back(info);
+ break;
+ case CMiddleWare::MW_ERROR:
+ Warning("Can not find debug dump directory for UUID: " + UUIDsUIDs[ii].first + ", deleting from database");
+ Status("Can not find debug dump directory for UUID: " + UUIDsUIDs[ii].first + ", deleting from database");
+ m_pMW->DeleteCrashInfo(UUIDsUIDs[ii].first, UUIDsUIDs[ii].second);
+ break;
+ case CMiddleWare::MW_FILE_ERROR:
+ {
+ std::string debugDumpDir;
+ Warning("Can not open file in debug dump directory for UUID: " + UUIDsUIDs[ii].first + ", deleting ");
+ Status("Can not open file in debug dump directory for UUID: " + UUIDsUIDs[ii].first + ", deleting ");
+ debugDumpDir = m_pMW->DeleteCrashInfo(UUIDsUIDs[ii].first, UUIDsUIDs[ii].second);
+ m_pMW->DeleteDebugDumpDir(debugDumpDir);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ catch (CABRTException& e)
+ {
+ if (e.type() == EXCEP_FATAL)
+ {
+ throw e;
+ }
+ Warning(e.what());
+ Status(e.what());
+ }
+
+ //retval = m_pMW->GetCrashInfos(pUID);
+ //Notify("Sent crash info");
+ return retval;
+}
+
+typedef struct thread_data_t {
+ pthread_t thread_id;
+ char* UUID;
+ char* UID;
+ char *dest;
+} thread_data_t;
+static void *create_report(void *arg)
+{
+ thread_data_t *thread_data = (thread_data_t *) arg;
+ map_crash_info_t crashReport;
+ g_cw->Debug("Creating report...");
+ try
+ {
+ CMiddleWare::mw_result_t res;
+ res = m_pMW->CreateCrashReport(thread_data->UUID, thread_data->UID, crashReport);
+ switch (res)
+ {
+ case CMiddleWare::MW_OK:
+ break;
+ case CMiddleWare::MW_IN_DB_ERROR:
+ g_cw->Warning(std::string("Did not find crash with UUID ")+thread_data->UUID+ " in database.");
+ break;
+ case CMiddleWare::MW_PLUGIN_ERROR:
+ g_cw->Warning(std::string("Particular analyzer plugin isn't loaded or there is an error within plugin(s)."));
+ break;
+ case CMiddleWare::MW_CORRUPTED:
+ case CMiddleWare::MW_FILE_ERROR:
+ default:
+ {
+ std::string debugDumpDir;
+ g_cw->Warning(std::string("Corrupted crash with UUID ")+thread_data->UUID+", deleting.");
+ debugDumpDir = m_pMW->DeleteCrashInfo(thread_data->UUID, thread_data->UID);
+ m_pMW->DeleteDebugDumpDir(debugDumpDir);
+ }
+ break;
+ }
+ /* only one thread can write */
+ pthread_mutex_lock(&m_pJobsMutex);
+ m_pending_jobs[std::string(thread_data->UID)][thread_data->thread_id] = crashReport;
+ pthread_mutex_unlock(&m_pJobsMutex);
+ m_pCommLayer->JobDone(thread_data->dest, thread_data->thread_id);
+ }
+ catch (CABRTException& e)
+ {
+ if (e.type() == EXCEP_FATAL)
+ {
+ /* free strduped strings */
+ free(thread_data->UUID);
+ free(thread_data->UID);
+ free(thread_data->dest);
+ free(thread_data);
+ throw e;
+ }
+ g_cw->Warning(e.what());
+ }
+ /* free strduped strings */
+ free(thread_data->UUID);
+ free(thread_data->UID);
+ free(thread_data->dest);
+ free(thread_data);
+
+ /* Bogus value. pthreads require us to return void* */
+ return NULL;
+}
+uint64_t CCrashWatcher::CreateReport_t(const std::string &pUUID,const std::string &pUID, const std::string &pSender)
+{
+ thread_data_t *thread_data = (thread_data_t *)xzalloc(sizeof(thread_data_t));
+ if (thread_data != NULL)
+ {
+ thread_data->UUID = xstrdup(pUUID.c_str());
+ thread_data->UID = xstrdup(pUID.c_str());
+ thread_data->dest = xstrdup(pSender.c_str());
+ if (pthread_create(&(thread_data->thread_id), NULL, create_report, (void *)thread_data) != 0)
+ {
+ throw CABRTException(EXCEP_FATAL, "CCrashWatcher::CreateReport_t(): Cannot create thread!");
+ }
+ }
+ else
+ {
+ throw CABRTException(EXCEP_FATAL, "CCrashWatcher::CreateReport_t(): Cannot allocate memory!");
+ }
+ //FIXME: we don't use this value anymore, so fix the API
+ return 0;
+}
+
+CMiddleWare::report_status_t CCrashWatcher::Report(map_crash_report_t pReport, const std::string& pUID)
+{
+ //#define FIELD(X) crashReport.m_s##X = pReport[#X];
+ //crashReport.m_sUUID = pReport["UUID"];
+ //ALL_CRASH_REPORT_FIELDS;
+ //#undef FIELD
+ //for (dbus_map_report_info_t::iterator it = pReport.begin(); it!=pReport.end(); ++it) {
+ // std::cerr << it->second << std::endl;
+ //}
+ CMiddleWare::report_status_t rs;
+ try
+ {
+ rs = m_pMW->Report(pReport, pUID);
+ }
+ catch (CABRTException& e)
+ {
+ if (e.type() == EXCEP_FATAL)
+ {
+ throw e;
+ }
+ Warning(e.what());
+ Status(e.what());
+ return rs;
+ }
+ return rs;
+}
+
+bool CCrashWatcher::DeleteDebugDump(const std::string& pUUID, const std::string& pUID)
+{
+ try
+ {
+ std::string debugDumpDir;
+ debugDumpDir = m_pMW->DeleteCrashInfo(pUUID,pUID);
+ m_pMW->DeleteDebugDumpDir(debugDumpDir);
+ }
+ catch (CABRTException& e)
+ {
+ if (e.type() == EXCEP_FATAL)
+ {
+ throw e;
+ }
+ Warning(e.what());
+ Status(e.what());
+ return false;
+ }
+ return true;
+}
+
+map_crash_report_t CCrashWatcher::GetJobResult(uint64_t pJobID, const std::string& pSender)
+{
+ /* FIXME: once we return the result, we should remove it from map to free memory
+ - use some TTL to clean the memory even if client won't get it
+ - if we don't find it in the cache we should try to ask MW to get it again??
+ */
+ return m_pending_jobs[pSender][pJobID];
+}
+
+vector_map_string_string_t CCrashWatcher::GetPluginsInfo()
+{
+ try
+ {
+ return m_pMW->GetPluginsInfo();
+ }
+ catch (CABRTException &e)
+ {
+ if (e.type() == EXCEP_FATAL)
+ {
+ throw e;
+ }
+ Warning(e.what());
+ }
+ // TODO: is it right? I added it just to disable a warning...
+ // but maybe returning empty map is wrong here?
+ return vector_map_string_string_t();
+}
+
+map_plugin_settings_t CCrashWatcher::GetPluginSettings(const std::string& pName, const std::string& pUID)
+{
+ try
+ {
+ return m_pMW->GetPluginSettings(pName, pUID);
+ }
+ catch(CABRTException &e)
+ {
+ if (e.type() == EXCEP_FATAL)
+ {
+ throw e;
+ }
+ Warning(e.what());
+ }
+}
+
+void CCrashWatcher::RegisterPlugin(const std::string& pName)
+{
+ try
+ {
+ m_pMW->RegisterPlugin(pName);
+ }
+ catch(CABRTException &e)
+ {
+ if (e.type() == EXCEP_FATAL)
+ {
+ throw e;
+ }
+ Warning(e.what());
+ }
+}
+
+void CCrashWatcher::UnRegisterPlugin(const std::string& pName)
+{
+ try
+ {
+ m_pMW->UnRegisterPlugin(pName);
+ }
+ catch(CABRTException &e)
+ {
+ if (e.type() == EXCEP_FATAL)
+ {
+ throw e;
+ }
+ Warning(e.what());
+ }
+}
+
+void CCrashWatcher::SetPluginSettings(const std::string& pName, const std::string& pUID, const map_plugin_settings_t& pSettings)
+{
+ try
+ {
+ m_pMW->SetPluginSettings(pName, pUID, pSettings);
+ }
+ catch(CABRTException &e)
+ {
+ if (e.type() == EXCEP_FATAL)
+ {
+ throw e;
+ }
+ Warning(e.what());
+ }
+}