summaryrefslogtreecommitdiffstats
path: root/src/journald
diff options
context:
space:
mode:
Diffstat (limited to 'src/journald')
-rw-r--r--src/journald/LMI_JournalLogRecordProvider.c112
-rw-r--r--src/journald/instutil.c29
-rw-r--r--src/journald/instutil.h2
3 files changed, 142 insertions, 1 deletions
diff --git a/src/journald/LMI_JournalLogRecordProvider.c b/src/journald/LMI_JournalLogRecordProvider.c
index 34a8f93..03493b3 100644
--- a/src/journald/LMI_JournalLogRecordProvider.c
+++ b/src/journald/LMI_JournalLogRecordProvider.c
@@ -21,6 +21,7 @@
#include <konkret/konkret.h>
#include <cmpi/cmpimacs.h>
#include "LMI_JournalLogRecord.h"
+#include "LMI_JournalMessageLog.h"
#include <errno.h>
#include <glib.h>
@@ -31,6 +32,9 @@
#include "instutil.h"
+#define WRITE_RECORD_TIMEOUT 5000 /* ms */
+
+
static const CMPIBroker* _cb = NULL;
static sd_journal *journal_iter = NULL;
@@ -161,6 +165,25 @@ static CMPIStatus LMI_JournalLogRecordGetInstance(
KReturn(OK);
}
+static const char *
+get_string_property(const char *property_name, const CMPIInstance* ci)
+{
+ CMPIData d;
+ CMPIStatus rc = { CMPI_RC_OK, NULL };
+
+ d = CMGetProperty(ci, property_name, &rc);
+ if (rc.rc != CMPI_RC_OK || (d.state & CMPI_nullValue) == CMPI_nullValue ||
+ (d.state & CMPI_notFound) == CMPI_notFound || d.value.string == NULL)
+ return NULL;
+ return CMGetCharPtr(d.value.string);
+}
+
+#define J_RESULT_CHECK(r,j,msg) \
+ if (r < 0) { \
+ sd_journal_close(j); \
+ KReturn2(_cb, ERR_FAILED, msg ": %s\n", strerror(-r)); \
+ }
+
static CMPIStatus LMI_JournalLogRecordCreateInstance(
CMPIInstanceMI* mi,
const CMPIContext* cc,
@@ -168,7 +191,94 @@ static CMPIStatus LMI_JournalLogRecordCreateInstance(
const CMPIObjectPath* cop,
const CMPIInstance* ci)
{
- CMReturn(CMPI_RC_ERR_NOT_SUPPORTED);
+ const char *cr_cl_n;
+ const char *log_cr_cl_n;
+ const char *log_name;
+ const char *data_format;
+ sd_journal *journal;
+ int r;
+ CMPIrc rc;
+ bool found;
+
+ cr_cl_n = get_string_property("CreationClassName", ci);
+ log_cr_cl_n = get_string_property("LogCreationClassName", ci);
+ log_name = get_string_property("LogName", ci);
+ data_format = get_string_property("DataFormat", ci);
+
+ if (cr_cl_n == NULL || log_cr_cl_n == NULL || log_name == NULL || data_format == NULL)
+ KReturn(ERR_INVALID_PARAMETER);
+ if (strcmp(cr_cl_n, LMI_JournalLogRecord_ClassName) != 0 ||
+ strcmp(log_cr_cl_n, LMI_JournalMessageLog_ClassName) != 0 ||
+ strcmp(log_name, JOURNAL_MESSAGE_LOG_NAME) != 0) {
+ KReturn(ERR_INVALID_PARAMETER);
+ }
+
+ r = sd_journal_open(&journal, 0);
+ if (r < 0) {
+ KReturn2(_cb, ERR_FAILED, "Error opening journal: %s\n", strerror(-r));
+ }
+
+ r = sd_journal_seek_tail(journal);
+ J_RESULT_CHECK(r, journal, "Error seeking to the end of the journal");
+
+ /* Need to call at least one of the _previous()/_next() functions to make the iterator set */
+ r = sd_journal_previous(journal);
+ if (r > 0)
+ while ((r = sd_journal_next(journal)) > 0)
+ ;
+ J_RESULT_CHECK(r, journal, "Error seeking to the end of the journal");
+
+ /* Queue send new record */
+ r = sd_journal_send("MESSAGE=%s", data_format,
+ NULL);
+ J_RESULT_CHECK(r, journal, "Error writing new record to the journal");
+
+ r = sd_journal_wait(journal, WRITE_RECORD_TIMEOUT * 1000 /* usec */);
+ /* First wait call will likely return INVALIDATE, try again */
+ if (r == SD_JOURNAL_INVALIDATE)
+ r = sd_journal_wait(journal, WRITE_RECORD_TIMEOUT * 1000 /* usec */);
+ J_RESULT_CHECK(r, journal, "Error checking the journal for new records");
+
+ found = false;
+ while (sd_journal_next(journal) > 0) {
+ /* TODO: alternatively, we can use custom property and an unique identifier
+ * but let's not bloat the journal with unneccessary data for now */
+ r = match_journal_record(journal, data_format, __func__);
+ if (r == 1) {
+ const char *ns = KNameSpace(cop);
+ LMI_JournalLogRecord log_record;
+ char *cursor;
+
+ LMI_JournalLogRecord_InitFromObjectPath(&log_record, _cb, cop);
+ LMI_JournalLogRecord_Set_DataFormat(&log_record, data_format);
+ LMI_JournalLogRecord_Set_CreationClassName(&log_record, LMI_JournalLogRecord_ClassName);
+ LMI_JournalLogRecord_Set_LogCreationClassName(&log_record, LMI_JournalMessageLog_ClassName);
+ LMI_JournalLogRecord_Set_LogName(&log_record, JOURNAL_MESSAGE_LOG_NAME);
+
+ /* Get stable cursor string */
+ r = sd_journal_get_cursor(journal, &cursor);
+ J_RESULT_CHECK(r, journal, "Failed to get cursor position");
+ LMI_JournalLogRecord_Set_RecordID(&log_record, cursor);
+ free(cursor);
+
+ r = create_LMI_JournalLogRecord(journal, &log_record, _cb);
+ if (r <= 0) {
+ sd_journal_close(journal);
+ KReturn2(_cb, ERR_FAILED, "Failed to create instance: %s\n", strerror(-r));
+ }
+
+ CMReturnObjectPath(cr, LMI_JournalLogRecord_ToObjectPath(&log_record, NULL));
+ CMReturnDone(cr);
+ found = true;
+ break;
+ }
+ J_RESULT_CHECK(r, journal, "Failed to find newly written record");
+ }
+ sd_journal_close(journal);
+
+ if (! found)
+ KReturn2(_cb, ERR_FAILED, "Failed to find newly written record\n");
+ CMReturn(CMPI_RC_OK);
}
static CMPIStatus LMI_JournalLogRecordModifyInstance(
diff --git a/src/journald/instutil.c b/src/journald/instutil.c
index a38202a..e664621 100644
--- a/src/journald/instutil.c
+++ b/src/journald/instutil.c
@@ -20,6 +20,7 @@
#include <errno.h>
#include <syslog.h>
+#include <unistd.h>
#include <glib.h>
#include <konkret/konkret.h>
@@ -239,6 +240,34 @@ int create_LMI_JournalLogRecord(sd_journal *j,
return 1;
}
+int match_journal_record(sd_journal *j, const char *message, const char *code_func)
+{
+ gchar *msg = NULL;
+ gchar *pid = NULL;
+ gchar *cfunc = NULL;
+ char *conv_err = NULL;
+ long int pid_n;
+ int r;
+
+ r = dup_journal_data(j, "MESSAGE", &msg);
+ if (r < 0)
+ return r;
+ dup_journal_data(j, "_PID", &pid);
+ dup_journal_data(j, "CODE_FUNC", &cfunc);
+
+ if (pid)
+ pid_n = strtol(pid, &conv_err, 10);
+
+ r = msg && pid && cfunc &&
+ (strcmp(message, msg) == 0) && (strcmp(code_func, cfunc) == 0) &&
+ (conv_err == NULL || *conv_err == '\0') && (pid_n == getpid());
+
+ g_free(msg);
+ g_free(pid);
+ g_free(cfunc);
+
+ return r;
+}
void ind_init()
{
diff --git a/src/journald/instutil.h b/src/journald/instutil.h
index 0ba7ff1..1ea96a2 100644
--- a/src/journald/instutil.h
+++ b/src/journald/instutil.h
@@ -31,6 +31,8 @@
int create_LMI_JournalLogRecordRef(sd_journal *j, LMI_JournalLogRecordRef *ref, const CMPIBroker *_cb);
int create_LMI_JournalLogRecord(sd_journal *j, LMI_JournalLogRecord *rec, const CMPIBroker *_cb);
+int match_journal_record(sd_journal *j, const char *message, const char *code_func);
+
void ind_init();
bool ind_watcher(void **data);
bool ind_filter_cb(const CMPISelectExp *filter);