summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Bzatek <tbzatek@redhat.com>2013-09-06 16:57:32 +0200
committerTomas Bzatek <tbzatek@redhat.com>2013-10-15 15:23:49 +0200
commit232956f843460b162bb3a1c341dbb9d633539ccf (patch)
tree021f7d0860d15f850c2cca5dfc96456fd37e9bf9
parentdc89f1d788001d4180acafbe51b4e64bdb1bde3f (diff)
downloadopenlmi-providers-232956f843460b162bb3a1c341dbb9d633539ccf.tar.gz
openlmi-providers-232956f843460b162bb3a1c341dbb9d633539ccf.tar.xz
openlmi-providers-232956f843460b162bb3a1c341dbb9d633539ccf.zip
journald: Add support for iterators
This implements CIM_MessageLog iterator functionality according to the model. The only limitation, or, let's say shortcoming, is a free-form output data format from the GetRecord call. Currently we feed the uint8 array with UTF-8 chars and it's up to the client to deal with it (as suggested in the model). This may be subject to change. Many methods are returning modified iterator that has been passed in and that allows having persistent iterators. As long as CIMOMs may destroy the instances and unload providers on inactivity, any particular delay would cause loss of the iterator. The iterator string contains journal cursor string, uniquely identifying a record. When this part of the iterator string is valid, the provider is able to reopen journal and seek to that position, allowing seamless continuation of the itearation process. If the cursor points to non-existing record, an error is returned. This typically happens when journal is rotated or the cursor is very old. The provider keeps track of active iterators during its lifetime, keeping the journal open for fast access. Clients are supposed to close the iterator by calling the CancelIteration method.
-rw-r--r--src/journald/LMI_JournalMessageLogProvider.c117
-rw-r--r--src/journald/instutil.c347
-rw-r--r--src/journald/instutil.h11
3 files changed, 462 insertions, 13 deletions
diff --git a/src/journald/LMI_JournalMessageLogProvider.c b/src/journald/LMI_JournalMessageLogProvider.c
index c4d9457..cde9a33 100644
--- a/src/journald/LMI_JournalMessageLogProvider.c
+++ b/src/journald/LMI_JournalMessageLogProvider.c
@@ -21,12 +21,19 @@
#include <konkret/konkret.h>
#include "LMI_JournalMessageLog.h"
+#include <glib.h>
#include <systemd/sd-journal.h>
#include "globals.h"
#include "journal.h"
+#include "instutil.h"
+/* As defined in CIM_MessageLog schema */
+#define CIM_MESSAGELOG_ITERATOR_RESULT_SUCCESS 0
+#define CIM_MESSAGELOG_ITERATOR_RESULT_NOT_SUPPORTED 1
+#define CIM_MESSAGELOG_ITERATOR_RESULT_FAILED 2
+
static const CMPIBroker* _cb = NULL;
static void LMI_JournalMessageLogInitialize()
@@ -204,6 +211,7 @@ KUint32 LMI_JournalMessageLog_ClearLog(
KUint32 result = KUINT32_INIT;
KSetStatus(status, ERR_NOT_SUPPORTED);
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_NOT_SUPPORTED);
return result;
}
@@ -216,8 +224,19 @@ KUint32 LMI_JournalMessageLog_PositionToFirstRecord(
CMPIStatus* status)
{
KUint32 result = KUINT32_INIT;
+ gchar *iter_id;
+
+ KSetStatus(status, OK);
+
+ if ((iter_id = journal_iter_new(NULL, NULL)) == NULL) {
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_FAILED);
+ return result;
+ }
+
+ KString_Set(IterationIdentifier, _cb, iter_id);
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_SUCCESS);
+ g_free(iter_id);
- KSetStatus(status, ERR_NOT_SUPPORTED);
return result;
}
@@ -232,8 +251,39 @@ KUint32 LMI_JournalMessageLog_PositionAtRecord(
CMPIStatus* status)
{
KUint32 result = KUINT32_INIT;
+ gchar *iter_id;
+ sd_journal *journal;
- KSetStatus(status, ERR_NOT_SUPPORTED);
+ if (IterationIdentifier->null || ! IterationIdentifier->exists ||
+ MoveAbsolute->null || ! MoveAbsolute->exists ||
+ RecordNumber->null || ! RecordNumber->exists) {
+ KSetStatus(status, ERR_INVALID_PARAMETER);
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_FAILED);
+ return result;
+ }
+
+ if (MoveAbsolute->value != 0) {
+ KSetStatus2(_cb, status, ERR_INVALID_PARAMETER, "Absolute movement not supported\n");
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_FAILED);
+ return result;
+ }
+
+ iter_id = g_strdup(IterationIdentifier->chars);
+ if (! journal_iter_validate_id(&iter_id, &journal, NULL, _cb, status)) {
+ g_free(iter_id);
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_FAILED);
+ return result;
+ }
+
+ if (! journal_iter_seek(&iter_id, journal, RecordNumber->value)) {
+ g_free(iter_id);
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_FAILED);
+ return result;
+ }
+
+ KString_Set(IterationIdentifier, _cb, iter_id);
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_SUCCESS);
+ g_free(iter_id);
return result;
}
@@ -249,8 +299,44 @@ KUint32 LMI_JournalMessageLog_GetRecord(
CMPIStatus* status)
{
KUint32 result = KUINT32_INIT;
+ gchar *iter_id;
+ sd_journal *journal;
+ char *data;
+ guint i;
+
+ if (IterationIdentifier->null || ! IterationIdentifier->exists ||
+ PositionToNext->null || ! PositionToNext->exists) {
+ KSetStatus(status, ERR_INVALID_PARAMETER);
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_FAILED);
+ return result;
+ }
- KSetStatus(status, ERR_NOT_SUPPORTED);
+ iter_id = g_strdup(IterationIdentifier->chars);
+ if (! journal_iter_validate_id(&iter_id, &journal, NULL, _cb, status)) {
+ g_free(iter_id);
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_FAILED);
+ return result;
+ }
+
+ data = journal_iter_get_data(&iter_id, journal, PositionToNext->value == 1);
+ if (! data) {
+ g_free(iter_id);
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_FAILED);
+ return result;
+ }
+
+ KUint8A_Init(RecordData, _cb, strlen(data));
+ /* FIXME: This will feed the array with unsigned chars, NOT terminated by zero.
+ * Ideally we would like to pass string instead but the model is given. */
+ /* TODO: do the real signed vs. unsigned char conversion? */
+ for (i = 0; i < strlen(data); i++)
+ KUint8A_Set(RecordData, i, (unsigned char) data[i]);
+
+ g_free(data);
+
+ KString_Set(IterationIdentifier, _cb, iter_id);
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_SUCCESS);
+ g_free(iter_id);
return result;
}
@@ -268,6 +354,7 @@ KUint32 LMI_JournalMessageLog_DeleteRecord(
KUint32 result = KUINT32_INIT;
KSetStatus(status, ERR_NOT_SUPPORTED);
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_NOT_SUPPORTED);
return result;
}
@@ -285,6 +372,7 @@ KUint32 LMI_JournalMessageLog_WriteRecord(
KUint32 result = KUINT32_INIT;
KSetStatus(status, ERR_NOT_SUPPORTED);
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_NOT_SUPPORTED);
return result;
}
@@ -297,8 +385,27 @@ KUint32 LMI_JournalMessageLog_CancelIteration(
CMPIStatus* status)
{
KUint32 result = KUINT32_INIT;
+ gchar *iter_id_short;
- KSetStatus(status, ERR_NOT_SUPPORTED);
+ if (IterationIdentifier->null || ! IterationIdentifier->exists) {
+ KSetStatus(status, ERR_INVALID_PARAMETER);
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_FAILED);
+ return result;
+ }
+
+ if (! journal_iter_parse_iterator_string(IterationIdentifier->chars, &iter_id_short, NULL, NULL)) {
+ KSetStatus2(_cb, status, ERR_INVALID_PARAMETER, "Malformed IterationIdentifier argument");
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_FAILED);
+ return result;
+ }
+
+ KSetStatus(status, OK);
+ if (journal_iter_cancel(iter_id_short))
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_SUCCESS);
+ else
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_FAILED);
+
+ g_free(iter_id_short);
return result;
}
@@ -313,6 +420,7 @@ KUint32 LMI_JournalMessageLog_FreezeLog(
KUint32 result = KUINT32_INIT;
KSetStatus(status, ERR_NOT_SUPPORTED);
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_NOT_SUPPORTED);
return result;
}
@@ -329,6 +437,7 @@ KUint32 LMI_JournalMessageLog_FlagRecordForOverwrite(
KUint32 result = KUINT32_INIT;
KSetStatus(status, ERR_NOT_SUPPORTED);
+ KUint32_Set(&result, CIM_MESSAGELOG_ITERATOR_RESULT_NOT_SUPPORTED);
return result;
}
diff --git a/src/journald/instutil.c b/src/journald/instutil.c
index ac9e768..a38202a 100644
--- a/src/journald/instutil.c
+++ b/src/journald/instutil.c
@@ -22,6 +22,9 @@
#include <syslog.h>
#include <glib.h>
+#include <konkret/konkret.h>
+#include <cmpi/cmpimacs.h>
+
#include "instutil.h"
#include "globals.h"
#include "journal.h"
@@ -33,6 +36,14 @@
/* Assuming no thread safety */
static sd_journal *ind_journal = NULL;
+/* LMI_JournalMessageLog iterators */
+static GHashTable *cmpi_iters = NULL;
+G_LOCK_DEFINE_STATIC(cmpi_iters);
+static sig_atomic_t cmpi_iters_count = 0;
+
+#define JOURNAL_ITER_PREFIX "LMI_JournalMessageLog_CMPI_Iter_"
+#define JOURNAL_ITER_SEPARATOR "#"
+
int create_LMI_JournalLogRecordRef(sd_journal *j,
LMI_JournalLogRecordRef *ref,
@@ -84,32 +95,60 @@ static int dup_journal_data(
return 0;
}
-int create_LMI_JournalLogRecord(sd_journal *j,
- LMI_JournalLogRecord *rec,
- const CMPIBroker *_cb)
+static int get_record_message(sd_journal *j, gboolean full_format, gchar **out)
{
int r;
- uint64_t usec;
- CMPIDateTime *date;
gchar *d;
gchar *syslog_identifier = NULL;
gchar *comm = NULL;
gchar *pid = NULL;
gchar *fake_pid = NULL;
+ gchar *realtime = NULL;
+ gchar *hostname = NULL;
GString *str;
- /* Construct the message */
+ str = g_string_new(NULL);
+ if (! str)
+ return -ENOMEM;
+
/* Message format is inspired by journalctl short output, containing the identifier (process name),
* PID and the message. In other words, it's the traditional syslog record format.
* Keep in sync with systemd:src/shared/logs-show.c:output_short() */
r = dup_journal_data(j, "MESSAGE", &d);
if (r < 0)
return r;
+
dup_journal_data(j, "SYSLOG_IDENTIFIER", &syslog_identifier);
dup_journal_data(j, "_COMM", &comm);
dup_journal_data(j, "_PID", &pid);
dup_journal_data(j, "SYSLOG_PID", &fake_pid);
- str = g_string_new(NULL);
+
+ if (full_format) {
+ /* Include timestamp and hostname */
+ char buf[64];
+ guint64 x = 0;
+ time_t t;
+ struct tm tm;
+ gchar *endptr = NULL;
+
+ dup_journal_data(j, "_SOURCE_REALTIME_TIMESTAMP", &realtime);
+ dup_journal_data(j, "_HOSTNAME", &hostname);
+ if (realtime) {
+ g_ascii_strtoull(realtime, &endptr, 10);
+ if (endptr != NULL && *endptr != '\0')
+ x = 0;
+ }
+ if (x == 0)
+ r = sd_journal_get_realtime_usec(j, &x);
+ if (r >= 0) {
+ t = (time_t) (x / 1000000ULL);
+ r = strftime(buf, sizeof(buf), "%b %d %H:%M:%S", localtime_r(&t, &tm));
+ if (r > 0)
+ g_string_append_printf(str, "%s ", buf);
+ }
+ if (hostname)
+ g_string_append_printf(str, "%s ", hostname);
+ }
if (syslog_identifier || comm)
g_string_append(str, syslog_identifier ? syslog_identifier : comm);
if (pid || fake_pid)
@@ -117,13 +156,33 @@ int create_LMI_JournalLogRecord(sd_journal *j,
if (str->len > 0)
g_string_append(str, ": ");
g_string_append(str, d);
- LMI_JournalLogRecord_Set_DataFormat(rec, str->str);
- g_string_free(str, TRUE);
+ *out = g_string_free(str, FALSE);
g_free(d);
g_free(syslog_identifier);
g_free(comm);
g_free(pid);
g_free(fake_pid);
+ g_free(realtime);
+ g_free(hostname);
+
+ return 0;
+}
+
+int create_LMI_JournalLogRecord(sd_journal *j,
+ LMI_JournalLogRecord *rec,
+ const CMPIBroker *_cb)
+{
+ int r;
+ uint64_t usec;
+ CMPIDateTime *date;
+ gchar *d;
+
+ /* Construct the message */
+ r = get_record_message(j, FALSE, &d);
+ if (r < 0)
+ return r;
+ LMI_JournalLogRecord_Set_DataFormat(rec, d);
+ g_free(d);
/* Set timestamp */
r = sd_journal_get_realtime_usec(j, &usec);
@@ -319,3 +378,273 @@ bool ind_filter_cb(const CMPISelectExp *filter)
if (strcasecmp(rhs_str, LMI_JournalLogRecord_ClassName) == 0) return true;
return false;
}
+
+/* --------------------------------------------------------------------------- */
+
+/* TODO: count references to the journal struct -- someone may cancel the iteration
+ * while others are still using the journal struct (racy) */
+
+#define set_cmpi_status_fmt(CB, STATUS, CODE, MSG, ...) \
+ { gchar *errs; \
+ errs = g_strdup_printf(MSG, ##__VA_ARGS__); \
+ KSetStatus2(CB, STATUS, CODE, errs); \
+ g_free(errs);\
+ }
+
+static gchar *
+make_iterator_string(sd_journal *journal, const char *cursor, gchar *iter_id_short)
+{
+ return g_strdup_printf("%s%s%p%s%s", iter_id_short, JOURNAL_ITER_SEPARATOR, (void *)journal, JOURNAL_ITER_SEPARATOR, cursor);
+}
+
+bool
+journal_iter_parse_iterator_string(const char *iter_id, gchar **out_iter_id_short, gpointer *out_iter_ptr, gchar **out_iter_cursor)
+{
+ gchar **s;
+ bool res;
+ gpointer valid_p;
+
+ res = (iter_id && strlen(iter_id) > 0);
+ if (res)
+ s = g_strsplit(iter_id, JOURNAL_ITER_SEPARATOR, 3);
+ res = res && s && g_strv_length(s) == 3 && strlen(s[0]) > 0 && strlen(s[1]) > 0 && strlen(s[2]) > 0;
+ valid_p = NULL;
+ res = res && (sscanf(s[1], "%p", &valid_p) == 1);
+ if (res && out_iter_id_short)
+ res = res && ((*out_iter_id_short = g_strdup(s[0])) != NULL);
+ if (res && out_iter_ptr)
+ *out_iter_ptr = valid_p;
+ if (res && out_iter_cursor)
+ res = res && ((*out_iter_cursor = g_strdup(s[2])) != NULL);
+ g_strfreev(s);
+
+ return res;
+}
+
+gchar *
+journal_iter_new(const gchar *req_cursor, sd_journal **journal_out)
+{
+ gchar *iter_id = NULL;
+ gchar *iter_id_full = NULL;
+ char *cursor;
+ sd_journal *journal;
+ int r;
+
+ if (journal_out)
+ *journal_out = NULL;
+
+ r = sd_journal_open(&journal, 0);
+ if (r < 0) {
+ error("Error opening journal: %s\n", strerror(-r));
+ return NULL;
+ }
+
+ if (req_cursor)
+ r = sd_journal_seek_cursor(journal, req_cursor);
+ else
+ r = sd_journal_seek_head(journal);
+
+ if (r < 0) {
+ error("Error seeking to the requested journal position: %s\n", strerror(-r));
+ sd_journal_close(journal);
+ return NULL;
+ }
+
+ r = sd_journal_next(journal);
+ if (r < 0) {
+ error("Error stepping next in the journal: %s\n", strerror(-r));
+ sd_journal_close(journal);
+ return NULL;
+ }
+
+ r = sd_journal_get_cursor(journal, &cursor);
+ if (r < 0) {
+ error("Error getting current cursor: %s\n", strerror(-r));
+ sd_journal_close(journal);
+ return NULL;
+ }
+
+ G_LOCK(cmpi_iters);
+ if (cmpi_iters == NULL)
+ cmpi_iters = g_hash_table_new_full(g_str_hash, g_str_equal, (GDestroyNotify) g_free, (GDestroyNotify) sd_journal_close);
+ if (cmpi_iters == NULL) {
+ error("Memory allocation failure\n");
+ sd_journal_close(journal);
+ G_UNLOCK(cmpi_iters);
+ return NULL;
+ }
+ iter_id = g_strdup_printf("%s%d", JOURNAL_ITER_PREFIX, cmpi_iters_count++);
+ if (iter_id)
+ iter_id_full = make_iterator_string(journal, cursor, iter_id);
+ if (iter_id == NULL || iter_id_full == NULL) {
+ error("Memory allocation failure\n");
+ sd_journal_close(journal);
+ } else {
+ g_hash_table_insert(cmpi_iters, iter_id, journal);
+ }
+ G_UNLOCK(cmpi_iters);
+
+ if (iter_id_full && journal_out)
+ *journal_out = journal;
+
+ return iter_id_full;
+}
+
+bool
+journal_iter_validate_id(gchar **iter_id, sd_journal **journal_out, gchar **prefix_out, const CMPIBroker *_cb, CMPIStatus *status)
+{
+ gboolean res;
+ gchar *iter_id_short, *iter_cursor;
+ gpointer iter_ptr;
+
+ res = TRUE;
+ if (journal_out)
+ *journal_out = NULL;
+ if (prefix_out)
+ *prefix_out = NULL;
+
+ if (! journal_iter_parse_iterator_string(*iter_id, &iter_id_short, &iter_ptr, &iter_cursor)) {
+ set_cmpi_status_fmt(_cb, status, ERR_INVALID_PARAMETER, "Malformed IterationIdentifier argument: \'%s\'\n", *iter_id);
+ return false;
+ }
+ KSetStatus(status, OK);
+
+ if (journal_out) {
+ G_LOCK(cmpi_iters);
+ if (cmpi_iters)
+ *journal_out = g_hash_table_lookup(cmpi_iters, iter_id_short);
+ G_UNLOCK(cmpi_iters);
+ if (*journal_out == NULL || *journal_out != iter_ptr) {
+ /* Assume stale iterator ID, reopen journal and try to find the position by the cursor */
+ warn("journal_iter_validate_id(): iterator pointer %p doesn't match with hashtable %p, reopening journal...\n", iter_ptr, *journal_out);
+ g_free(*iter_id);
+ *iter_id = journal_iter_new(iter_cursor, journal_out);
+ if (*iter_id == NULL) {
+ error("The IterationIdentifier is not valid anymore: \'%s\'\n", *iter_id);
+ res = FALSE;
+ }
+ }
+ }
+
+ if (res && prefix_out) {
+ /* No need to check prefix validity as it's supposed to be used in journal_iter_cancel() only */
+ res = res && ((*prefix_out = g_strdup(iter_id_short)) != NULL);
+ }
+
+ g_free(iter_id_short);
+ g_free(iter_cursor);
+ return res;
+}
+
+
+bool
+journal_iter_cancel(const char *iter_id)
+{
+ gboolean b;
+
+ g_return_val_if_fail(iter_id != NULL, false);
+
+ G_LOCK(cmpi_iters);
+ b = cmpi_iters && g_hash_table_remove(cmpi_iters, iter_id);
+ G_UNLOCK(cmpi_iters);
+ if (! b) {
+ error("IterationIdentifier \'%s\' not registered\n", iter_id);
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+update_iter(gchar **iter_id, sd_journal *journal)
+{
+ gchar *iter_id_short;
+ char *cursor;
+ int r;
+
+ r = sd_journal_get_cursor(journal, &cursor);
+ if (r < 0) {
+ error("Error getting current cursor: %s\n", strerror(-r));
+ return false;
+ }
+
+ if (! journal_iter_parse_iterator_string(*iter_id, &iter_id_short, NULL, NULL))
+ return false;
+ *iter_id = make_iterator_string(journal, cursor, iter_id_short);
+ return *iter_id != NULL;
+}
+
+
+bool
+journal_iter_seek(gchar **iter_id, sd_journal *journal, gint64 position)
+{
+ int r;
+
+ g_return_val_if_fail(journal != NULL, false);
+
+ if (position == 0) { /* NOP */
+ warn("journal_iter_seek(): Spurious seek request to relative position 0\n");
+ return true;
+ }
+
+ if (position > 0)
+ r = sd_journal_next_skip(journal, position);
+ else
+ r = sd_journal_previous_skip(journal, -position);
+
+ if (r < 0) {
+ error("Error seeking to the requested position: %s\n", strerror(-r));
+ return false;
+ }
+
+ if (! update_iter(iter_id, journal)) {
+ error("Error seeking to the requested position\n");
+ return false;
+ }
+
+ return true;
+}
+
+gchar *
+journal_iter_get_data(gchar **iter_id, sd_journal *journal, gboolean step_next)
+{
+ gchar *d;
+ int r;
+
+ g_return_val_if_fail(journal != NULL, false);
+
+ /* Construct the message */
+ r = get_record_message(journal, TRUE, &d);
+ if (r < 0) {
+ error("Error getting record message: %s\n", strerror(-r));
+ return NULL;
+ }
+
+ if (step_next) {
+ r = sd_journal_next(journal);
+ if (r < 0) {
+ error("Error advancing to the next record: %s\n", strerror(-r));
+ g_free(d);
+ return NULL;
+ }
+ }
+
+ if (! update_iter(iter_id, journal)) {
+ error("Error getting record message\n");
+ return NULL;
+ }
+
+ return d;
+}
+
+/* FIXME: unused for the moment as the hash table is global, shared across instances */
+void
+journal_iters_destroy()
+{
+ G_LOCK(cmpi_iters);
+ if (cmpi_iters != NULL) {
+ g_hash_table_destroy(cmpi_iters);
+ cmpi_iters = NULL;
+ }
+ G_UNLOCK(cmpi_iters);
+}
diff --git a/src/journald/instutil.h b/src/journald/instutil.h
index ee823c5..0ba7ff1 100644
--- a/src/journald/instutil.h
+++ b/src/journald/instutil.h
@@ -21,6 +21,8 @@
#ifndef INSTUTIL_H_
#define INSTUTIL_H_
+#include <glib.h>
+#include <konkret/konkret.h>
#include <systemd/sd-journal.h>
#include <ind_manager.h>
@@ -35,4 +37,13 @@ bool ind_filter_cb(const CMPISelectExp *filter);
bool ind_gather(const IMManager *manager, CMPIInstance **old, CMPIInstance **new, void *data);
void ind_destroy();
+gchar * journal_iter_new(const gchar *req_cursor, sd_journal **journal_out);
+bool journal_iter_parse_iterator_string(const char *iter_id, gchar **out_iter_id_short, gpointer *out_iter_ptr, gchar **out_iter_cursor);
+bool journal_iter_validate_id(gchar **iter_id, sd_journal **journal_out, gchar **prefix_out, const CMPIBroker *_cb, CMPIStatus *status);
+bool journal_iter_cancel(const gchar *iter_id);
+bool journal_iter_seek(gchar **iter_id, sd_journal *journal, gint64 position);
+gchar * journal_iter_get_data(gchar **iter_id, sd_journal *journal, gboolean step_next);
+void journal_iters_destroy();
+
+
#endif /* INSTUTIL_H_ */