1
/*-*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*-*/
4
This file is part of systemd.
6
Copyright 2013 Steven Hiscocks, Zbigniew Jędrzejewski-Szmek
8
systemd is free software; you can redistribute it and/or modify it
9
under the terms of the GNU Lesser General Public License as published by
10
the Free Software Foundation; either version 2.1 of the License, or
11
(at your option) any later version.
13
systemd is distributed in the hope that it will be useful, but
14
WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
Lesser General Public License for more details.
18
You should have received a copy of the GNU Lesser General Public License
19
along with systemd; If not, see <http://www.gnu.org/licenses/>.
23
#include <structmember.h>
28
#include <systemd/sd-journal.h>
39
static PyTypeObject ReaderType;
41
static int set_error(int r, const char* path, const char* invalid_message) {
44
if (r == -EINVAL && invalid_message)
45
PyErr_SetString(PyExc_ValueError, invalid_message);
46
else if (r == -ENOMEM)
47
PyErr_SetString(PyExc_MemoryError, "Not enough memory");
50
PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
56
PyDoc_STRVAR(module__doc__,
57
"Class to reads the systemd journal similar to journalctl.");
60
#if PY_MAJOR_VERSION >= 3
61
static PyTypeObject MonotonicType;
63
PyDoc_STRVAR(MonotonicType__doc__,
64
"A tuple of (timestamp, bootid) for holding monotonic timestamps");
66
static PyStructSequence_Field MonotonicType_fields[] = {
67
{(char*) "timestamp", (char*) "Time"},
68
{(char*) "bootid", (char*) "Unique identifier of the boot"},
72
static PyStructSequence_Desc Monotonic_desc = {
73
(char*) "journal.Monotonic",
81
static void Reader_dealloc(Reader* self)
83
sd_journal_close(self->j);
84
Py_TYPE(self)->tp_free((PyObject*)self);
87
PyDoc_STRVAR(Reader__doc__,
88
"_Reader([flags | path]) -> ...\n\n"
89
"_Reader allows filtering and retrieval of Journal entries.\n"
90
"Note: this is a low-level interface, and probably not what you\n"
91
"want, use systemd.journal.Reader instead.\n\n"
92
"Argument `flags` sets open flags of the journal, which can be one\n"
93
"of, or ORed combination of constants: LOCAL_ONLY (default) opens\n"
94
"journal on local machine only; RUNTIME_ONLY opens only\n"
95
"volatile journal files; and SYSTEM_ONLY opens only\n"
96
"journal files of system services and the kernel.\n\n"
97
"Argument `path` is the directory of journal files. Note that\n"
98
"`flags` and `path` are exclusive.\n\n"
99
"_Reader implements the context manager protocol: the journal\n"
100
"will be closed when exiting the block.");
101
static int Reader_init(Reader *self, PyObject *args, PyObject *keywds)
106
static const char* const kwlist[] = {"flags", "path", NULL};
107
if (!PyArg_ParseTupleAndKeywords(args, keywds, "|iz", (char**) kwlist,
112
flags = SD_JOURNAL_LOCAL_ONLY;
115
PyErr_SetString(PyExc_ValueError, "cannot use both flags and path");
119
Py_BEGIN_ALLOW_THREADS
121
r = sd_journal_open_directory(&self->j, path, 0);
123
r = sd_journal_open(&self->j, flags);
126
return set_error(r, path, "Invalid flags or path");
130
PyDoc_STRVAR(Reader_fileno__doc__,
131
"fileno() -> int\n\n"
132
"Get a file descriptor to poll for changes in the journal.\n"
133
"This method invokes sd_journal_get_fd().\n"
134
"See man:sd_journal_get_fd(3).");
135
static PyObject* Reader_fileno(Reader *self, PyObject *args)
137
int fd = sd_journal_get_fd(self->j);
138
set_error(fd, NULL, NULL);
141
return long_FromLong(fd);
145
PyDoc_STRVAR(Reader_reliable_fd__doc__,
146
"reliable_fd() -> bool\n\n"
147
"Returns True iff the journal can be polled reliably.\n"
148
"This method invokes sd_journal_reliable_fd().\n"
149
"See man:sd_journal_reliable_fd(3).");
150
static PyObject* Reader_reliable_fd(Reader *self, PyObject *args)
152
int r = sd_journal_reliable_fd(self->j);
153
set_error(r, NULL, NULL);
156
return PyBool_FromLong(r);
160
PyDoc_STRVAR(Reader_get_events__doc__,
161
"get_events() -> int\n\n"
162
"Returns a mask of poll() events to wait for on the file\n"
163
"descriptor returned by .fileno().\n\n"
164
"See man:sd_journal_get_events(3) for further discussion.");
165
static PyObject* Reader_get_events(Reader *self, PyObject *args)
167
int r = sd_journal_get_events(self->j);
168
set_error(r, NULL, NULL);
171
return long_FromLong(r);
175
PyDoc_STRVAR(Reader_get_timeout__doc__,
176
"get_timeout() -> int or None\n\n"
177
"Returns a timeout value for usage in poll(), the time since the\n"
178
"epoch of clock_gettime(2) in microseconds, or None if no timeout\n"
180
"The return value must be converted to a relative timeout in \n"
181
"milliseconds if it is to be used as an argument for poll().\n"
182
"See man:sd_journal_get_timeout(3) for further discussion.");
183
static PyObject* Reader_get_timeout(Reader *self, PyObject *args)
188
r = sd_journal_get_timeout(self->j, &t);
189
set_error(r, NULL, NULL);
193
if (t == (uint64_t) -1)
196
assert_cc(sizeof(unsigned long long) == sizeof(t));
197
return PyLong_FromUnsignedLongLong(t);
201
PyDoc_STRVAR(Reader_get_timeout_ms__doc__,
202
"get_timeout_ms() -> int\n\n"
203
"Returns a timeout value suitable for usage in poll(), the value\n"
204
"returned by .get_timeout() converted to relative ms, or -1 if\n"
205
"no timeout is necessary.");
206
static PyObject* Reader_get_timeout_ms(Reader *self, PyObject *args)
211
r = sd_journal_get_timeout(self->j, &t);
212
set_error(r, NULL, NULL);
216
return absolute_timeout(t);
220
PyDoc_STRVAR(Reader_close__doc__,
221
"close() -> None\n\n"
222
"Free resources allocated by this Reader object.\n"
223
"This method invokes sd_journal_close().\n"
224
"See man:sd_journal_close(3).");
225
static PyObject* Reader_close(Reader *self, PyObject *args)
230
sd_journal_close(self->j);
236
PyDoc_STRVAR(Reader_get_usage__doc__,
237
"get_usage() -> int\n\n"
238
"Returns the total disk space currently used by journal\n"
239
"files (in bytes). If `SD_JOURNAL_LOCAL_ONLY` was\n"
240
"passed when opening the journal this value will only reflect\n"
241
"the size of journal files of the local host, otherwise\n"
243
"This method invokes sd_journal_get_usage().\n"
244
"See man:sd_journal_get_usage(3).");
245
static PyObject* Reader_get_usage(Reader *self, PyObject *args)
250
r = sd_journal_get_usage(self->j, &bytes);
251
if (set_error(r, NULL, NULL))
254
assert_cc(sizeof(unsigned long long) == sizeof(bytes));
255
return PyLong_FromUnsignedLongLong(bytes);
259
PyDoc_STRVAR(Reader___enter____doc__,
260
"__enter__() -> self\n\n"
261
"Part of the context manager protocol.\n"
263
static PyObject* Reader___enter__(PyObject *self, PyObject *args)
272
PyDoc_STRVAR(Reader___exit____doc__,
273
"__exit__(type, value, traceback) -> None\n\n"
274
"Part of the context manager protocol.\n"
275
"Closes the journal.\n");
276
static PyObject* Reader___exit__(Reader *self, PyObject *args)
280
sd_journal_close(self->j);
286
PyDoc_STRVAR(Reader_next__doc__,
287
"next([skip]) -> bool\n\n"
288
"Go to the next log entry. Optional skip value means to go to\n"
289
"the `skip`\\-th log entry.\n"
290
"Returns False if at end of file, True otherwise.");
291
static PyObject* Reader_next(Reader *self, PyObject *args)
296
if (!PyArg_ParseTuple(args, "|L:next", &skip))
300
PyErr_SetString(PyExc_ValueError, "skip must be nonzero");
304
Py_BEGIN_ALLOW_THREADS
306
r = sd_journal_next(self->j);
307
else if (skip == -1LL)
308
r = sd_journal_previous(self->j);
310
r = sd_journal_next_skip(self->j, skip);
311
else if (skip < -1LL)
312
r = sd_journal_previous_skip(self->j, -skip);
314
assert_not_reached("should not be here");
317
set_error(r, NULL, NULL);
320
return PyBool_FromLong(r);
323
PyDoc_STRVAR(Reader_previous__doc__,
324
"previous([skip]) -> bool\n\n"
325
"Go to the previous log entry. Optional skip value means to \n"
326
"go to the `skip`\\-th previous log entry.\n"
327
"Returns False if at start of file, True otherwise.");
328
static PyObject* Reader_previous(Reader *self, PyObject *args)
331
if (!PyArg_ParseTuple(args, "|L:previous", &skip))
334
return PyObject_CallMethod((PyObject *)self, (char*) "_next",
339
static int extract(const char* msg, size_t msg_len,
340
PyObject **key, PyObject **value) {
341
PyObject *k = NULL, *v;
342
const char *delim_ptr;
344
delim_ptr = memchr(msg, '=', msg_len);
346
PyErr_SetString(PyExc_OSError,
347
"journal gave us a field without '='");
352
k = unicode_FromStringAndSize(msg, delim_ptr - (const char*) msg);
358
v = PyBytes_FromStringAndSize(delim_ptr + 1,
359
(const char*) msg + msg_len - (delim_ptr + 1));
374
PyDoc_STRVAR(Reader_get__doc__,
375
"get(str) -> str\n\n"
376
"Return data associated with this key in current log entry.\n"
377
"Throws KeyError is the data is not available.");
378
static PyObject* Reader_get(Reader *self, PyObject *args)
389
if (!PyArg_ParseTuple(args, "s:get", &field))
392
r = sd_journal_get_data(self->j, field, &msg, &msg_len);
394
PyErr_SetString(PyExc_KeyError, field);
396
} else if (set_error(r, NULL, "field name is not valid"))
399
r = extract(msg, msg_len, NULL, &value);
406
PyDoc_STRVAR(Reader_get_all__doc__,
407
"_get_all() -> dict\n\n"
408
"Return dictionary of the current log entry.");
409
static PyObject* Reader_get_all(Reader *self, PyObject *args)
420
SD_JOURNAL_FOREACH_DATA(self->j, msg, msg_len) {
421
_cleanup_Py_DECREF_ PyObject *key = NULL, *value = NULL;
423
r = extract(msg, msg_len, &key, &value);
427
if (PyDict_Contains(dict, key)) {
428
PyObject *cur_value = PyDict_GetItem(dict, key);
430
if (PyList_CheckExact(cur_value)) {
431
r = PyList_Append(cur_value, value);
435
_cleanup_Py_DECREF_ PyObject *tmp_list = PyList_New(0);
439
r = PyList_Append(tmp_list, cur_value);
443
r = PyList_Append(tmp_list, value);
447
r = PyDict_SetItem(dict, key, tmp_list);
452
r = PyDict_SetItem(dict, key, value);
466
PyDoc_STRVAR(Reader_get_realtime__doc__,
467
"get_realtime() -> int\n\n"
468
"Return the realtime timestamp for the current journal entry\n"
469
"in microseconds.\n\n"
470
"Wraps sd_journal_get_realtime_usec().\n"
471
"See man:sd_journal_get_realtime_usec(3).");
472
static PyObject* Reader_get_realtime(Reader *self, PyObject *args)
480
r = sd_journal_get_realtime_usec(self->j, ×tamp);
481
if (set_error(r, NULL, NULL))
484
assert_cc(sizeof(unsigned long long) == sizeof(timestamp));
485
return PyLong_FromUnsignedLongLong(timestamp);
489
PyDoc_STRVAR(Reader_get_monotonic__doc__,
490
"get_monotonic() -> (timestamp, bootid)\n\n"
491
"Return the monotonic timestamp for the current journal entry\n"
492
"as a tuple of time in microseconds and bootid.\n\n"
493
"Wraps sd_journal_get_monotonic_usec().\n"
494
"See man:sd_journal_get_monotonic_usec(3).");
495
static PyObject* Reader_get_monotonic(Reader *self, PyObject *args)
499
PyObject *monotonic, *bootid, *tuple;
505
r = sd_journal_get_monotonic_usec(self->j, ×tamp, &id);
506
if (set_error(r, NULL, NULL))
509
assert_cc(sizeof(unsigned long long) == sizeof(timestamp));
510
monotonic = PyLong_FromUnsignedLongLong(timestamp);
511
bootid = PyBytes_FromStringAndSize((const char*) &id.bytes, sizeof(id.bytes));
512
#if PY_MAJOR_VERSION >= 3
513
tuple = PyStructSequence_New(&MonotonicType);
515
tuple = PyTuple_New(2);
517
if (!monotonic || !bootid || !tuple) {
518
Py_XDECREF(monotonic);
524
#if PY_MAJOR_VERSION >= 3
525
PyStructSequence_SET_ITEM(tuple, 0, monotonic);
526
PyStructSequence_SET_ITEM(tuple, 1, bootid);
528
PyTuple_SET_ITEM(tuple, 0, monotonic);
529
PyTuple_SET_ITEM(tuple, 1, bootid);
535
PyDoc_STRVAR(Reader_add_match__doc__,
536
"add_match(match) -> None\n\n"
537
"Add a match to filter journal log entries. All matches of different\n"
538
"fields are combined with logical AND, and matches of the same field\n"
539
"are automatically combined with logical OR.\n"
540
"Match is a string of the form \"FIELD=value\".");
541
static PyObject* Reader_add_match(Reader *self, PyObject *args, PyObject *keywds)
545
if (!PyArg_ParseTuple(args, "s#:add_match", &match, &match_len))
548
r = sd_journal_add_match(self->j, match, match_len);
549
set_error(r, NULL, "Invalid match");
557
PyDoc_STRVAR(Reader_add_disjunction__doc__,
558
"add_disjunction() -> None\n\n"
559
"Inserts a logical OR between matches added since previous\n"
560
"add_disjunction() or add_conjunction() and the next\n"
561
"add_disjunction() or add_conjunction().\n\n"
562
"See man:sd_journal_add_disjunction(3) for explanation.");
563
static PyObject* Reader_add_disjunction(Reader *self, PyObject *args)
566
r = sd_journal_add_disjunction(self->j);
567
set_error(r, NULL, NULL);
574
PyDoc_STRVAR(Reader_add_conjunction__doc__,
575
"add_conjunction() -> None\n\n"
576
"Inserts a logical AND between matches added since previous\n"
577
"add_disjunction() or add_conjunction() and the next\n"
578
"add_disjunction() or add_conjunction().\n\n"
579
"See man:sd_journal_add_disjunction(3) for explanation.");
580
static PyObject* Reader_add_conjunction(Reader *self, PyObject *args)
583
r = sd_journal_add_conjunction(self->j);
584
set_error(r, NULL, NULL);
591
PyDoc_STRVAR(Reader_flush_matches__doc__,
592
"flush_matches() -> None\n\n"
593
"Clear all current match filters.");
594
static PyObject* Reader_flush_matches(Reader *self, PyObject *args)
596
sd_journal_flush_matches(self->j);
601
PyDoc_STRVAR(Reader_seek_head__doc__,
602
"seek_head() -> None\n\n"
603
"Jump to the beginning of the journal.\n"
604
"This method invokes sd_journal_seek_head().\n"
605
"See man:sd_journal_seek_head(3).");
606
static PyObject* Reader_seek_head(Reader *self, PyObject *args)
609
Py_BEGIN_ALLOW_THREADS
610
r = sd_journal_seek_head(self->j);
612
if (set_error(r, NULL, NULL))
618
PyDoc_STRVAR(Reader_seek_tail__doc__,
619
"seek_tail() -> None\n\n"
620
"Jump to the end of the journal.\n"
621
"This method invokes sd_journal_seek_tail().\n"
622
"See man:sd_journal_seek_tail(3).");
623
static PyObject* Reader_seek_tail(Reader *self, PyObject *args)
626
Py_BEGIN_ALLOW_THREADS
627
r = sd_journal_seek_tail(self->j);
629
if (set_error(r, NULL, NULL))
635
PyDoc_STRVAR(Reader_seek_realtime__doc__,
636
"seek_realtime(realtime) -> None\n\n"
637
"Seek to nearest matching journal entry to `realtime`. Argument\n"
638
"`realtime` in specified in seconds.");
639
static PyObject* Reader_seek_realtime(Reader *self, PyObject *args)
644
if (!PyArg_ParseTuple(args, "K:seek_realtime", ×tamp))
647
Py_BEGIN_ALLOW_THREADS
648
r = sd_journal_seek_realtime_usec(self->j, timestamp);
650
if (set_error(r, NULL, NULL))
656
PyDoc_STRVAR(Reader_seek_monotonic__doc__,
657
"seek_monotonic(monotonic[, bootid]) -> None\n\n"
658
"Seek to nearest matching journal entry to `monotonic`. Argument\n"
659
"`monotonic` is an timestamp from boot in microseconds.\n"
660
"Argument `bootid` is a string representing which boot the\n"
661
"monotonic time is reference to. Defaults to current bootid.");
662
static PyObject* Reader_seek_monotonic(Reader *self, PyObject *args)
669
if (!PyArg_ParseTuple(args, "K|z:seek_monotonic", ×tamp, &bootid))
673
r = sd_id128_from_string(bootid, &id);
674
if (set_error(r, NULL, "Invalid bootid"))
677
Py_BEGIN_ALLOW_THREADS
678
r = sd_id128_get_boot(&id);
680
if (set_error(r, NULL, NULL))
684
Py_BEGIN_ALLOW_THREADS
685
r = sd_journal_seek_monotonic_usec(self->j, id, timestamp);
687
if (set_error(r, NULL, NULL))
694
PyDoc_STRVAR(Reader_process__doc__,
695
"process() -> state change (integer)\n\n"
696
"Process events and reset the readable state of the file\n"
697
"descriptor returned by .fileno().\n\n"
698
"Will return constants: NOP if no change; APPEND if new\n"
699
"entries have been added to the end of the journal; and\n"
700
"INVALIDATE if journal files have been added or removed.\n\n"
701
"See man:sd_journal_process(3) for further discussion.");
702
static PyObject* Reader_process(Reader *self, PyObject *args)
708
Py_BEGIN_ALLOW_THREADS
709
r = sd_journal_process(self->j);
711
if (set_error(r, NULL, NULL) < 0)
714
return long_FromLong(r);
718
PyDoc_STRVAR(Reader_wait__doc__,
719
"wait([timeout]) -> state change (integer)\n\n"
720
"Wait for a change in the journal. Argument `timeout` specifies\n"
721
"the maximum number of microseconds to wait before returning\n"
722
"regardless of wheter the journal has changed. If `timeout` is -1,\n"
723
"then block forever.\n\n"
724
"Will return constants: NOP if no change; APPEND if new\n"
725
"entries have been added to the end of the journal; and\n"
726
"INVALIDATE if journal files have been added or removed.\n\n"
727
"See man:sd_journal_wait(3) for further discussion.");
728
static PyObject* Reader_wait(Reader *self, PyObject *args)
733
if (!PyArg_ParseTuple(args, "|L:wait", &timeout))
736
Py_BEGIN_ALLOW_THREADS
737
r = sd_journal_wait(self->j, timeout);
739
if (set_error(r, NULL, NULL) < 0)
742
return long_FromLong(r);
746
PyDoc_STRVAR(Reader_seek_cursor__doc__,
747
"seek_cursor(cursor) -> None\n\n"
748
"Seek to journal entry by given unique reference `cursor`.");
749
static PyObject* Reader_seek_cursor(Reader *self, PyObject *args)
754
if (!PyArg_ParseTuple(args, "s:seek_cursor", &cursor))
757
Py_BEGIN_ALLOW_THREADS
758
r = sd_journal_seek_cursor(self->j, cursor);
760
if (set_error(r, NULL, "Invalid cursor"))
766
PyDoc_STRVAR(Reader_get_cursor__doc__,
767
"get_cursor() -> str\n\n"
768
"Return a cursor string for the current journal entry.\n\n"
769
"Wraps sd_journal_get_cursor(). See man:sd_journal_get_cursor(3).");
770
static PyObject* Reader_get_cursor(Reader *self, PyObject *args)
772
_cleanup_free_ char *cursor = NULL;
778
r = sd_journal_get_cursor(self->j, &cursor);
779
if (set_error(r, NULL, NULL))
782
return unicode_FromString(cursor);
786
PyDoc_STRVAR(Reader_test_cursor__doc__,
787
"test_cursor(str) -> bool\n\n"
788
"Test whether the cursor string matches current journal entry.\n\n"
789
"Wraps sd_journal_test_cursor(). See man:sd_journal_test_cursor(3).");
790
static PyObject* Reader_test_cursor(Reader *self, PyObject *args)
798
if (!PyArg_ParseTuple(args, "s:test_cursor", &cursor))
801
r = sd_journal_test_cursor(self->j, cursor);
802
set_error(r, NULL, NULL);
806
return PyBool_FromLong(r);
809
PyDoc_STRVAR(Reader_query_unique__doc__,
810
"query_unique(field) -> a set of values\n\n"
811
"Return a set of unique values appearing in journal for the\n"
812
"given `field`. Note this does not respect any journal matches.");
813
static PyObject* Reader_query_unique(Reader *self, PyObject *args)
819
PyObject *value_set, *key, *value;
821
if (!PyArg_ParseTuple(args, "s:query_unique", &query))
824
Py_BEGIN_ALLOW_THREADS
825
r = sd_journal_query_unique(self->j, query);
827
if (set_error(r, NULL, "Invalid field name"))
830
value_set = PySet_New(0);
831
key = unicode_FromString(query);
833
SD_JOURNAL_FOREACH_UNIQUE(self->j, uniq, uniq_len) {
834
const char *delim_ptr;
836
delim_ptr = memchr(uniq, '=', uniq_len);
837
value = PyBytes_FromStringAndSize(
839
(const char*) uniq + uniq_len - (delim_ptr + 1));
840
PySet_Add(value_set, value);
848
PyDoc_STRVAR(Reader_get_catalog__doc__,
849
"get_catalog() -> str\n\n"
850
"Retrieve a message catalog entry for the current journal entry.\n"
851
"Will throw IndexError if the entry has no MESSAGE_ID\n"
852
"and KeyError is the id is specified, but hasn't been found\n"
853
"in the catalog.\n\n"
854
"Wraps man:sd_journal_get_catalog(3).");
855
static PyObject* Reader_get_catalog(Reader *self, PyObject *args)
858
_cleanup_free_ char *msg = NULL;
863
Py_BEGIN_ALLOW_THREADS
864
r = sd_journal_get_catalog(self->j, &msg);
870
r = sd_journal_get_data(self->j, "MESSAGE_ID", &mid, &mid_len);
872
const int l = sizeof("MESSAGE_ID");
874
PyErr_Format(PyExc_KeyError, "%.*s", (int) mid_len - l,
875
(const char*) mid + l);
876
} else if (r == -ENOENT)
877
PyErr_SetString(PyExc_IndexError, "no MESSAGE_ID field");
879
set_error(r, NULL, NULL);
881
} else if (set_error(r, NULL, NULL))
884
return unicode_FromString(msg);
888
PyDoc_STRVAR(get_catalog__doc__,
889
"get_catalog(id128) -> str\n\n"
890
"Retrieve a message catalog entry for the given id.\n"
891
"Wraps man:sd_journal_get_catalog_for_message_id(3).");
892
static PyObject* get_catalog(PyObject *self, PyObject *args)
897
_cleanup_free_ char *msg = NULL;
902
if (!PyArg_ParseTuple(args, "z:get_catalog", &id_))
905
r = sd_id128_from_string(id_, &id);
906
if (set_error(r, NULL, "Invalid id128"))
909
Py_BEGIN_ALLOW_THREADS
910
r = sd_journal_get_catalog_for_message_id(id, &msg);
912
if (set_error(r, NULL, NULL))
915
return unicode_FromString(msg);
919
PyDoc_STRVAR(data_threshold__doc__,
920
"Threshold for field size truncation in bytes.\n\n"
921
"Fields longer than this will be truncated to the threshold size.\n"
922
"Defaults to 64Kb.");
924
static PyObject* Reader_get_data_threshold(Reader *self, void *closure)
929
r = sd_journal_get_data_threshold(self->j, &cvalue);
930
if (set_error(r, NULL, NULL))
933
return long_FromSize_t(cvalue);
936
static int Reader_set_data_threshold(Reader *self, PyObject *value, void *closure)
940
PyErr_SetString(PyExc_AttributeError, "Cannot delete data threshold");
943
if (!long_Check(value)){
944
PyErr_SetString(PyExc_TypeError, "Data threshold must be an int");
947
r = sd_journal_set_data_threshold(self->j, (size_t) long_AsLong(value));
948
return set_error(r, NULL, NULL);
952
PyDoc_STRVAR(closed__doc__,
953
"True iff journal is closed");
954
static PyObject* Reader_get_closed(Reader *self, void *closure)
956
return PyBool_FromLong(self->j == NULL);
960
static PyGetSetDef Reader_getsetters[] = {
961
{(char*) "data_threshold",
962
(getter) Reader_get_data_threshold,
963
(setter) Reader_set_data_threshold,
964
(char*) data_threshold__doc__,
967
(getter) Reader_get_closed,
969
(char*) closed__doc__,
974
static PyMethodDef Reader_methods[] = {
975
{"fileno", (PyCFunction) Reader_fileno, METH_NOARGS, Reader_fileno__doc__},
976
{"reliable_fd", (PyCFunction) Reader_reliable_fd, METH_NOARGS, Reader_reliable_fd__doc__},
977
{"get_events", (PyCFunction) Reader_get_events, METH_NOARGS, Reader_get_events__doc__},
978
{"get_timeout", (PyCFunction) Reader_get_timeout, METH_NOARGS, Reader_get_timeout__doc__},
979
{"get_timeout_ms", (PyCFunction) Reader_get_timeout_ms, METH_NOARGS, Reader_get_timeout_ms__doc__},
980
{"close", (PyCFunction) Reader_close, METH_NOARGS, Reader_close__doc__},
981
{"get_usage", (PyCFunction) Reader_get_usage, METH_NOARGS, Reader_get_usage__doc__},
982
{"__enter__", (PyCFunction) Reader___enter__, METH_NOARGS, Reader___enter____doc__},
983
{"__exit__", (PyCFunction) Reader___exit__, METH_VARARGS, Reader___exit____doc__},
984
{"_next", (PyCFunction) Reader_next, METH_VARARGS, Reader_next__doc__},
985
{"_previous", (PyCFunction) Reader_previous, METH_VARARGS, Reader_previous__doc__},
986
{"_get", (PyCFunction) Reader_get, METH_VARARGS, Reader_get__doc__},
987
{"_get_all", (PyCFunction) Reader_get_all, METH_NOARGS, Reader_get_all__doc__},
988
{"_get_realtime", (PyCFunction) Reader_get_realtime, METH_NOARGS, Reader_get_realtime__doc__},
989
{"_get_monotonic", (PyCFunction) Reader_get_monotonic, METH_NOARGS, Reader_get_monotonic__doc__},
990
{"add_match", (PyCFunction) Reader_add_match, METH_VARARGS|METH_KEYWORDS, Reader_add_match__doc__},
991
{"add_disjunction", (PyCFunction) Reader_add_disjunction, METH_NOARGS, Reader_add_disjunction__doc__},
992
{"add_conjunction", (PyCFunction) Reader_add_conjunction, METH_NOARGS, Reader_add_conjunction__doc__},
993
{"flush_matches", (PyCFunction) Reader_flush_matches, METH_NOARGS, Reader_flush_matches__doc__},
994
{"seek_head", (PyCFunction) Reader_seek_head, METH_NOARGS, Reader_seek_head__doc__},
995
{"seek_tail", (PyCFunction) Reader_seek_tail, METH_NOARGS, Reader_seek_tail__doc__},
996
{"seek_realtime", (PyCFunction) Reader_seek_realtime, METH_VARARGS, Reader_seek_realtime__doc__},
997
{"seek_monotonic", (PyCFunction) Reader_seek_monotonic, METH_VARARGS, Reader_seek_monotonic__doc__},
998
{"process", (PyCFunction) Reader_process, METH_NOARGS, Reader_process__doc__},
999
{"wait", (PyCFunction) Reader_wait, METH_VARARGS, Reader_wait__doc__},
1000
{"seek_cursor", (PyCFunction) Reader_seek_cursor, METH_VARARGS, Reader_seek_cursor__doc__},
1001
{"_get_cursor", (PyCFunction) Reader_get_cursor, METH_NOARGS, Reader_get_cursor__doc__},
1002
{"test_cursor", (PyCFunction) Reader_test_cursor, METH_VARARGS, Reader_test_cursor__doc__},
1003
{"query_unique", (PyCFunction) Reader_query_unique, METH_VARARGS, Reader_query_unique__doc__},
1004
{"get_catalog", (PyCFunction) Reader_get_catalog, METH_NOARGS, Reader_get_catalog__doc__},
1008
static PyTypeObject ReaderType = {
1009
PyVarObject_HEAD_INIT(NULL, 0)
1010
"_reader._Reader", /*tp_name*/
1011
sizeof(Reader), /*tp_basicsize*/
1013
(destructor)Reader_dealloc, /*tp_dealloc*/
1020
0, /*tp_as_sequence*/
1021
0, /*tp_as_mapping*/
1028
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
1029
Reader__doc__, /* tp_doc */
1030
0, /* tp_traverse */
1032
0, /* tp_richcompare */
1033
0, /* tp_weaklistoffset */
1035
0, /* tp_iternext */
1036
Reader_methods, /* tp_methods */
1038
Reader_getsetters, /* tp_getset */
1041
0, /* tp_descr_get */
1042
0, /* tp_descr_set */
1043
0, /* tp_dictoffset */
1044
(initproc) Reader_init, /* tp_init */
1046
PyType_GenericNew, /* tp_new */
1049
static PyMethodDef methods[] = {
1050
{ "_get_catalog", get_catalog, METH_VARARGS, get_catalog__doc__},
1051
{ NULL, NULL, 0, NULL } /* Sentinel */
1054
#if PY_MAJOR_VERSION >= 3
1055
static PyModuleDef module = {
1056
PyModuleDef_HEAD_INIT,
1061
NULL, NULL, NULL, NULL
1065
#if PY_MAJOR_VERSION >= 3
1066
static bool initialized = false;
1069
#pragma GCC diagnostic push
1070
#pragma GCC diagnostic ignored "-Wmissing-prototypes"
1073
#if PY_MAJOR_VERSION >= 3
1074
PyInit__reader(void)
1083
if (PyType_Ready(&ReaderType) < 0)
1084
#if PY_MAJOR_VERSION >= 3
1090
#if PY_MAJOR_VERSION >= 3
1091
m = PyModule_Create(&module);
1096
PyStructSequence_InitType(&MonotonicType, &Monotonic_desc);
1100
m = Py_InitModule3("_reader", methods, module__doc__);
1105
Py_INCREF(&ReaderType);
1106
#if PY_MAJOR_VERSION >= 3
1107
Py_INCREF(&MonotonicType);
1109
if (PyModule_AddObject(m, "_Reader", (PyObject *) &ReaderType) ||
1110
#if PY_MAJOR_VERSION >= 3
1111
PyModule_AddObject(m, "Monotonic", (PyObject*) &MonotonicType) ||
1113
PyModule_AddIntConstant(m, "NOP", SD_JOURNAL_NOP) ||
1114
PyModule_AddIntConstant(m, "APPEND", SD_JOURNAL_APPEND) ||
1115
PyModule_AddIntConstant(m, "INVALIDATE", SD_JOURNAL_INVALIDATE) ||
1116
PyModule_AddIntConstant(m, "LOCAL_ONLY", SD_JOURNAL_LOCAL_ONLY) ||
1117
PyModule_AddIntConstant(m, "RUNTIME_ONLY", SD_JOURNAL_RUNTIME_ONLY) ||
1118
PyModule_AddIntConstant(m, "SYSTEM_ONLY", SD_JOURNAL_SYSTEM_ONLY) ||
1119
PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION)) {
1120
#if PY_MAJOR_VERSION >= 3
1126
#if PY_MAJOR_VERSION >= 3
1131
#pragma GCC diagnostic pop