Really Get Correct log entries from journal! && GUADEC
July, 10, 2018
The most memorable thing about this period is to participate in GUADEC–2018. Since there will be a blog dedicated to what you have seen and heard during GUADEC, I won’t go into details here.
Entering the theme, it is obvious that after meeting with my two mentors, some of my problems have been solved.
About reading new log messages and how to set up a correct cursor system
Next is the specific idea (corrected by the mentors)
Use the most simply way to complete it, so this time I have to consider a whole more, and consider the relevant details.
Initialization: Every time you need to read the latest end from the last end, that is, cursor_last to end of journal, so the correctness of the value stored in cursor_last is crucial. After all kinds of thinking, go to the following strategy. : Since sd_journal_previous() is called after the initialization of the model is completed, the cursor is rolled back to the position of a previous time node (this can be seen in gl_journal_model_fetch_idle() in gl-journal-model.c), which is about 50. I can’t guarantee the position before the line, because this line contains headers, a header may have many items, and all of them may be much larger than 50, but if the system log is less, less It is also very common in 50. Well, this problem seems to be less relevant to the problems considered in the past. It is especially necessary to initialize the first step. This is the crowning touch and it takes a long time in this place. For some tests, it is better to initialize the cursor_last at the end of the gl_journal_set_start_position function.
Intermediate process: Since the foundation of the first step is already in place, the next thing is much simpler. First, call sd_journal_seek_cursor(,).
sd_journal_seek_cursor() seeks to the entry located at the specified
cursor string. Note that these calls do not actually make any entry
the new current entry, this needs to be done in a separate step with a
subsequent sd_journal_next(3) invocation (or a similar Call).
Going back to the end of the last time, next, there is a more critical issue, about sd_journal_next(), which needs to be called twice, about the specific function of this function,
sd_journal_next() advances the read pointer into the journal by one
entry. The only argument taken is a journal context object as
allocated via sd_journal_open(3).
As can be seen from the above, it is necessary to call twice in succession, the first is Advance the read pointer into the journal by current log entry, and the second is Advance the read pointer to the first new available log entry.
The next time, A single “append” signal could indicate one or more newly added log entries, set a loop to iterate from the first new log entry to the end of the journal. Finally, according to the last valid entry read The value of the cursor is updated on cursor_last.
There is also a more important situation, that is, after the new news comes, the first step is to detect it first, to determine whether it can be added to the current category, but later I did some experiments to dispel this. Concerns, is not needed, gl_journal_set_matches (), this function has been filtered according to the current query to ensure that there will be no data other than the secondary query added, it must be said that this is a very good idea.
End: Since cursor_last is a variable inside the class, it needs to be freed, so as not to cause memory leaks.
static void
gl_journal_get_new_entry (GlJournal *self)
{
gint ret;
GlJournalEntry *entry;
GlJournalPrivate *priv = gl_journal_get_instance_private (self);
if(priv->cursor_last == NULL)
{
return;
}
/* Seek to the log entry located at the cursor_last */
ret = sd_journal_seek_cursor (priv->journal, priv->cursor_last);
if (ret < 0)
{
g_warning ("Error seeking to cursor of journal: %s",
g_strerror (-ret));
}
/* Advance the read pointer into the journal by current log entry */
ret = sd_journal_next (priv->journal);
if (ret < 0)
{
g_warning ("Error advancing the read pointer in the journal: %s",
g_strerror (-ret));
return;
}
/* Meet the end of the journal */
else if (ret == 0)
{
g_debug ("Meet the end of the journal");
return;
}
/* Advance the read pointer to the first new available log entry */
ret = sd_journal_next (priv->journal);
if (ret < 0)
{
g_warning ("Error advancing the read pointer in the journal: %s",
g_strerror (-ret));
return;
}
else if (ret == 0)
{
g_debug ("Meet the end of the journal");
return;
}
/* A single "append" signal could indicate one or more newly added
* log entries, set a loop to iterate from the first new log entry
* to the end of the journal */
while (ret > 0)
{
entry = _gl_journal_query_entry (self);
if (entry == NULL)
{
break;
}
/* Emit the signal and send the new log entry to gl-journal-model.c */
g_signal_emit (self, entries_signal, 0, entry);
ret = sd_journal_next (priv->journal);
if (ret < 0)
{
g_warning ("Error advancing the read pointer in the journal: %s",
g_strerror (-ret));
break;
}
else if (ret == 0)
{
g_debug ("Meet the end of the journal");
break;
}
}
if (entry == NULL)
{
return;
}
g_free (priv->cursor_last);
priv->cursor_last = g_strdup (entry->cursor);
}
I have a question. It’s such a simple method. I used to have so many mistakes when I realized it. I wasted a lot of time. It really shouldn’t be, but I just finished it.
Then go all out to complete the display of the item!
Go to the beach to play!