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>
38 static PyTypeObject ReaderType;
40 static int set_error(int r, const char* path, const char* invalid_message) {
43 if (r == -EINVAL && invalid_message)
44 PyErr_SetString(PyExc_ValueError, invalid_message);
45 else if (r == -ENOMEM)
46 PyErr_SetString(PyExc_MemoryError, "Not enough memory");
49 PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
55 PyDoc_STRVAR(module__doc__,
56 "Class to reads the systemd journal similar to journalctl.");
59 #if PY_MAJOR_VERSION >= 3
60 static PyTypeObject MonotonicType;
62 PyDoc_STRVAR(MonotonicType__doc__,
63 "A tuple of (timestamp, bootid) for holding monotonic timestamps");
65 static PyStructSequence_Field MonotonicType_fields[] = {
66 {(char*) "timestamp", (char*) "Time"},
67 {(char*) "bootid", (char*) "Unique identifier of the boot"},
71 static PyStructSequence_Desc Monotonic_desc = {
72 (char*) "journal.Monotonic",
80 static void Reader_dealloc(Reader* self)
82 sd_journal_close(self->j);
83 Py_TYPE(self)->tp_free((PyObject*)self);
86 PyDoc_STRVAR(Reader__doc__,
87 "_Reader([flags | path]) -> ...\n\n"
88 "_Reader allows filtering and retrieval of Journal entries.\n"
89 "Note: this is a low-level interface, and probably not what you\n"
90 "want, use systemd.journal.Reader instead.\n\n"
91 "Argument `flags` sets open flags of the journal, which can be one\n"
92 "of, or ORed combination of constants: LOCAL_ONLY (default) opens\n"
93 "journal on local machine only; RUNTIME_ONLY opens only\n"
94 "volatile journal files; and SYSTEM_ONLY opens only\n"
95 "journal files of system services and the kernel.\n\n"
96 "Argument `path` is the directory of journal files. Note that\n"
97 "`flags` and `path` are exclusive.\n\n"
98 "_Reader implements the context manager protocol: the journal\n"
99 "will be closed when exiting the block.");
100 static int Reader_init(Reader *self, PyObject *args, PyObject *keywds)
105 static const char* const kwlist[] = {"flags", "path", NULL};
106 if (!PyArg_ParseTupleAndKeywords(args, keywds, "|iz", (char**) kwlist,
111 flags = SD_JOURNAL_LOCAL_ONLY;
114 PyErr_SetString(PyExc_ValueError, "cannot use both flags and path");
118 Py_BEGIN_ALLOW_THREADS
120 r = sd_journal_open_directory(&self->j, path, 0);
122 r = sd_journal_open(&self->j, flags);
125 return set_error(r, path, "Invalid flags or path");
129 PyDoc_STRVAR(Reader_fileno__doc__,
130 "fileno() -> int\n\n"
131 "Get a file descriptor to poll for changes in the journal.\n"
132 "This method invokes sd_journal_get_fd().\n"
133 "See man:sd_journal_get_fd(3).");
134 static PyObject* Reader_fileno(Reader *self, PyObject *args)
136 int fd = sd_journal_get_fd(self->j);
137 set_error(fd, NULL, NULL);
140 return long_FromLong(fd);
144 PyDoc_STRVAR(Reader_reliable_fd__doc__,
145 "reliable_fd() -> bool\n\n"
146 "Returns True iff the journal can be polled reliably.\n"
147 "This method invokes sd_journal_reliable_fd().\n"
148 "See man:sd_journal_reliable_fd(3).");
149 static PyObject* Reader_reliable_fd(Reader *self, PyObject *args)
151 int r = sd_journal_reliable_fd(self->j);
152 set_error(r, NULL, NULL);
155 return PyBool_FromLong(r);
159 PyDoc_STRVAR(Reader_get_events__doc__,
160 "get_events() -> int\n\n"
161 "Returns a mask of poll() events to wait for on the file\n"
162 "descriptor returned by .fileno().\n\n"
163 "See man:sd_journal_get_events(3) for further discussion.");
164 static PyObject* Reader_get_events(Reader *self, PyObject *args)
166 int r = sd_journal_get_events(self->j);
167 set_error(r, NULL, NULL);
170 return long_FromLong(r);
174 PyDoc_STRVAR(Reader_get_timeout__doc__,
175 "get_timeout() -> int or None\n\n"
176 "Returns a timeout value for usage in poll(), the time since the\n"
177 "epoch of clock_gettime(2) in microseconds, or None if no timeout\n"
179 "The return value must be converted to a relative timeout in \n"
180 "milliseconds if it is to be used as an argument for poll().\n"
181 "See man:sd_journal_get_timeout(3) for further discussion.");
182 static PyObject* Reader_get_timeout(Reader *self, PyObject *args)
187 r = sd_journal_get_timeout(self->j, &t);
188 set_error(r, NULL, NULL);
192 if (t == (uint64_t) -1)
195 assert_cc(sizeof(unsigned long long) == sizeof(t));
196 return PyLong_FromUnsignedLongLong(t);
200 PyDoc_STRVAR(Reader_get_timeout_ms__doc__,
201 "get_timeout_ms() -> int\n\n"
202 "Returns a timeout value suitable for usage in poll(), the value\n"
203 "returned by .get_timeout() converted to relative ms, or -1 if\n"
204 "no timeout is necessary.");
205 static PyObject* Reader_get_timeout_ms(Reader *self, PyObject *args)
210 r = sd_journal_get_timeout(self->j, &t);
211 set_error(r, NULL, NULL);
215 if (t == (uint64_t) -1)
216 return PyLong_FromLong(-1);
222 clock_gettime(CLOCK_MONOTONIC, &ts);
223 n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
224 msec = t > n ? (int) ((t - n + 999) / 1000) : 0;
226 return PyLong_FromLong(msec);
231 PyDoc_STRVAR(Reader_close__doc__,
232 "close() -> None\n\n"
233 "Free resources allocated by this Reader object.\n"
234 "This method invokes sd_journal_close().\n"
235 "See man:sd_journal_close(3).");
236 static PyObject* Reader_close(Reader *self, PyObject *args)
241 sd_journal_close(self->j);
247 PyDoc_STRVAR(Reader_get_usage__doc__,
248 "get_usage() -> int\n\n"
249 "Returns the total disk space currently used by journal\n"
250 "files (in bytes). If `SD_JOURNAL_LOCAL_ONLY` was\n"
251 "passed when opening the journal this value will only reflect\n"
252 "the size of journal files of the local host, otherwise\n"
254 "This method invokes sd_journal_get_usage().\n"
255 "See man:sd_journal_get_usage(3).");
256 static PyObject* Reader_get_usage(Reader *self, PyObject *args)
261 r = sd_journal_get_usage(self->j, &bytes);
262 if (set_error(r, NULL, NULL))
265 assert_cc(sizeof(unsigned long long) == sizeof(bytes));
266 return PyLong_FromUnsignedLongLong(bytes);
270 PyDoc_STRVAR(Reader___enter____doc__,
271 "__enter__() -> self\n\n"
272 "Part of the context manager protocol.\n"
274 static PyObject* Reader___enter__(PyObject *self, PyObject *args)
283 PyDoc_STRVAR(Reader___exit____doc__,
284 "__exit__(type, value, traceback) -> None\n\n"
285 "Part of the context manager protocol.\n"
286 "Closes the journal.\n");
287 static PyObject* Reader___exit__(Reader *self, PyObject *args)
291 sd_journal_close(self->j);
297 PyDoc_STRVAR(Reader_next__doc__,
298 "next([skip]) -> bool\n\n"
299 "Go to the next log entry. Optional skip value means to go to\n"
300 "the `skip`\\-th log entry.\n"
301 "Returns False if at end of file, True otherwise.");
302 static PyObject* Reader_next(Reader *self, PyObject *args)
307 if (!PyArg_ParseTuple(args, "|L:next", &skip))
311 PyErr_SetString(PyExc_ValueError, "skip must be nonzero");
315 Py_BEGIN_ALLOW_THREADS
317 r = sd_journal_next(self->j);
318 else if (skip == -1LL)
319 r = sd_journal_previous(self->j);
321 r = sd_journal_next_skip(self->j, skip);
322 else if (skip < -1LL)
323 r = sd_journal_previous_skip(self->j, -skip);
325 assert_not_reached("should not be here");
328 set_error(r, NULL, NULL);
331 return PyBool_FromLong(r);
334 PyDoc_STRVAR(Reader_previous__doc__,
335 "previous([skip]) -> bool\n\n"
336 "Go to the previous log entry. Optional skip value means to \n"
337 "go to the `skip`\\-th previous log entry.\n"
338 "Returns False if at start of file, True otherwise.");
339 static PyObject* Reader_previous(Reader *self, PyObject *args)
342 if (!PyArg_ParseTuple(args, "|L:previous", &skip))
345 return PyObject_CallMethod((PyObject *)self, (char*) "_next",
350 static int extract(const char* msg, size_t msg_len,
351 PyObject **key, PyObject **value) {
352 PyObject *k = NULL, *v;
353 const char *delim_ptr;
355 delim_ptr = memchr(msg, '=', msg_len);
357 PyErr_SetString(PyExc_OSError,
358 "journal gave us a field without '='");
363 k = unicode_FromStringAndSize(msg, delim_ptr - (const char*) msg);
369 v = PyBytes_FromStringAndSize(delim_ptr + 1,
370 (const char*) msg + msg_len - (delim_ptr + 1));
385 PyDoc_STRVAR(Reader_get__doc__,
386 "get(str) -> str\n\n"
387 "Return data associated with this key in current log entry.\n"
388 "Throws KeyError is the data is not available.");
389 static PyObject* Reader_get(Reader *self, PyObject *args)
400 if (!PyArg_ParseTuple(args, "s:get", &field))
403 r = sd_journal_get_data(self->j, field, &msg, &msg_len);
405 PyErr_SetString(PyExc_KeyError, field);
407 } else if (set_error(r, NULL, "field name is not valid"))
410 r = extract(msg, msg_len, NULL, &value);
417 PyDoc_STRVAR(Reader_get_all__doc__,
418 "_get_all() -> dict\n\n"
419 "Return dictionary of the current log entry.");
420 static PyObject* Reader_get_all(Reader *self, PyObject *args)
431 SD_JOURNAL_FOREACH_DATA(self->j, msg, msg_len) {
432 PyObject _cleanup_Py_DECREF_ *key = NULL, *value = NULL;
434 r = extract(msg, msg_len, &key, &value);
438 if (PyDict_Contains(dict, key)) {
439 PyObject *cur_value = PyDict_GetItem(dict, key);
441 if (PyList_CheckExact(cur_value)) {
442 r = PyList_Append(cur_value, value);
446 PyObject _cleanup_Py_DECREF_ *tmp_list = PyList_New(0);
450 r = PyList_Append(tmp_list, cur_value);
454 r = PyList_Append(tmp_list, value);
458 r = PyDict_SetItem(dict, key, tmp_list);
463 r = PyDict_SetItem(dict, key, value);
477 PyDoc_STRVAR(Reader_get_realtime__doc__,
478 "get_realtime() -> int\n\n"
479 "Return the realtime timestamp for the current journal entry\n"
480 "in microseconds.\n\n"
481 "Wraps sd_journal_get_realtime_usec().\n"
482 "See man:sd_journal_get_realtime_usec(3).");
483 static PyObject* Reader_get_realtime(Reader *self, PyObject *args)
491 r = sd_journal_get_realtime_usec(self->j, ×tamp);
492 if (set_error(r, NULL, NULL))
495 assert_cc(sizeof(unsigned long long) == sizeof(timestamp));
496 return PyLong_FromUnsignedLongLong(timestamp);
500 PyDoc_STRVAR(Reader_get_monotonic__doc__,
501 "get_monotonic() -> (timestamp, bootid)\n\n"
502 "Return the monotonic timestamp for the current journal entry\n"
503 "as a tuple of time in microseconds and bootid.\n\n"
504 "Wraps sd_journal_get_monotonic_usec().\n"
505 "See man:sd_journal_get_monotonic_usec(3).");
506 static PyObject* Reader_get_monotonic(Reader *self, PyObject *args)
510 PyObject *monotonic, *bootid, *tuple;
516 r = sd_journal_get_monotonic_usec(self->j, ×tamp, &id);
517 if (set_error(r, NULL, NULL))
520 assert_cc(sizeof(unsigned long long) == sizeof(timestamp));
521 monotonic = PyLong_FromUnsignedLongLong(timestamp);
522 bootid = PyBytes_FromStringAndSize((const char*) &id.bytes, sizeof(id.bytes));
523 #if PY_MAJOR_VERSION >= 3
524 tuple = PyStructSequence_New(&MonotonicType);
526 tuple = PyTuple_New(2);
528 if (!monotonic || !bootid || !tuple) {
529 Py_XDECREF(monotonic);
535 #if PY_MAJOR_VERSION >= 3
536 PyStructSequence_SET_ITEM(tuple, 0, monotonic);
537 PyStructSequence_SET_ITEM(tuple, 1, bootid);
539 PyTuple_SET_ITEM(tuple, 0, monotonic);
540 PyTuple_SET_ITEM(tuple, 1, bootid);
546 PyDoc_STRVAR(Reader_add_match__doc__,
547 "add_match(match) -> None\n\n"
548 "Add a match to filter journal log entries. All matches of different\n"
549 "fields are combined with logical AND, and matches of the same field\n"
550 "are automatically combined with logical OR.\n"
551 "Match is a string of the form \"FIELD=value\".");
552 static PyObject* Reader_add_match(Reader *self, PyObject *args, PyObject *keywds)
556 if (!PyArg_ParseTuple(args, "s#:add_match", &match, &match_len))
559 r = sd_journal_add_match(self->j, match, match_len);
560 set_error(r, NULL, "Invalid match");
568 PyDoc_STRVAR(Reader_add_disjunction__doc__,
569 "add_disjunction() -> None\n\n"
570 "Inserts a logical OR between matches added before and afterwards.");
571 static PyObject* Reader_add_disjunction(Reader *self, PyObject *args)
574 r = sd_journal_add_disjunction(self->j);
575 set_error(r, NULL, NULL);
582 PyDoc_STRVAR(Reader_flush_matches__doc__,
583 "flush_matches() -> None\n\n"
584 "Clear all current match filters.");
585 static PyObject* Reader_flush_matches(Reader *self, PyObject *args)
587 sd_journal_flush_matches(self->j);
592 PyDoc_STRVAR(Reader_seek_head__doc__,
593 "seek_head() -> None\n\n"
594 "Jump to the beginning of the journal.\n"
595 "This method invokes sd_journal_seek_head().\n"
596 "See man:sd_journal_seek_head(3).");
597 static PyObject* Reader_seek_head(Reader *self, PyObject *args)
600 Py_BEGIN_ALLOW_THREADS
601 r = sd_journal_seek_head(self->j);
603 if (set_error(r, NULL, NULL))
609 PyDoc_STRVAR(Reader_seek_tail__doc__,
610 "seek_tail() -> None\n\n"
611 "Jump to the end of the journal.\n"
612 "This method invokes sd_journal_seek_tail().\n"
613 "See man:sd_journal_seek_tail(3).");
614 static PyObject* Reader_seek_tail(Reader *self, PyObject *args)
617 Py_BEGIN_ALLOW_THREADS
618 r = sd_journal_seek_tail(self->j);
620 if (set_error(r, NULL, NULL))
626 PyDoc_STRVAR(Reader_seek_realtime__doc__,
627 "seek_realtime(realtime) -> None\n\n"
628 "Seek to nearest matching journal entry to `realtime`. Argument\n"
629 "`realtime` in specified in seconds.");
630 static PyObject* Reader_seek_realtime(Reader *self, PyObject *args)
635 if (!PyArg_ParseTuple(args, "K:seek_realtime", ×tamp))
638 Py_BEGIN_ALLOW_THREADS
639 r = sd_journal_seek_realtime_usec(self->j, timestamp);
641 if (set_error(r, NULL, NULL))
647 PyDoc_STRVAR(Reader_seek_monotonic__doc__,
648 "seek_monotonic(monotonic[, bootid]) -> None\n\n"
649 "Seek to nearest matching journal entry to `monotonic`. Argument\n"
650 "`monotonic` is an timestamp from boot in microseconds.\n"
651 "Argument `bootid` is a string representing which boot the\n"
652 "monotonic time is reference to. Defaults to current bootid.");
653 static PyObject* Reader_seek_monotonic(Reader *self, PyObject *args)
660 if (!PyArg_ParseTuple(args, "K|z:seek_monotonic", ×tamp, &bootid))
664 r = sd_id128_from_string(bootid, &id);
665 if (set_error(r, NULL, "Invalid bootid"))
668 Py_BEGIN_ALLOW_THREADS
669 r = sd_id128_get_boot(&id);
671 if (set_error(r, NULL, NULL))
675 Py_BEGIN_ALLOW_THREADS
676 r = sd_journal_seek_monotonic_usec(self->j, id, timestamp);
678 if (set_error(r, NULL, NULL))
685 PyDoc_STRVAR(Reader_process__doc__,
686 "process() -> state change (integer)\n\n"
687 "Process events and reset the readable state of the file\n"
688 "descriptor returned by .fileno().\n\n"
689 "Will return constants: NOP if no change; APPEND if new\n"
690 "entries have been added to the end of the journal; and\n"
691 "INVALIDATE if journal files have been added or removed.\n\n"
692 "See man:sd_journal_process(3) for further discussion.");
693 static PyObject* Reader_process(Reader *self, PyObject *args)
699 Py_BEGIN_ALLOW_THREADS
700 r = sd_journal_process(self->j);
702 if (set_error(r, NULL, NULL) < 0)
705 return long_FromLong(r);
709 PyDoc_STRVAR(Reader_wait__doc__,
710 "wait([timeout]) -> state change (integer)\n\n"
711 "Wait for a change in the journal. Argument `timeout` specifies\n"
712 "the maximum number of microseconds to wait before returning\n"
713 "regardless of wheter the journal has changed. If `timeout` is -1,\n"
714 "then block forever.\n\n"
715 "Will return constants: NOP if no change; APPEND if new\n"
716 "entries have been added to the end of the journal; and\n"
717 "INVALIDATE if journal files have been added or removed.\n\n"
718 "See man:sd_journal_wait(3) for further discussion.");
719 static PyObject* Reader_wait(Reader *self, PyObject *args)
724 if (!PyArg_ParseTuple(args, "|L:wait", &timeout))
727 Py_BEGIN_ALLOW_THREADS
728 r = sd_journal_wait(self->j, timeout);
730 if (set_error(r, NULL, NULL) < 0)
733 return long_FromLong(r);
737 PyDoc_STRVAR(Reader_seek_cursor__doc__,
738 "seek_cursor(cursor) -> None\n\n"
739 "Seek to journal entry by given unique reference `cursor`.");
740 static PyObject* Reader_seek_cursor(Reader *self, PyObject *args)
745 if (!PyArg_ParseTuple(args, "s:seek_cursor", &cursor))
748 Py_BEGIN_ALLOW_THREADS
749 r = sd_journal_seek_cursor(self->j, cursor);
751 if (set_error(r, NULL, "Invalid cursor"))
757 PyDoc_STRVAR(Reader_get_cursor__doc__,
758 "get_cursor() -> str\n\n"
759 "Return a cursor string for the current journal entry.\n\n"
760 "Wraps sd_journal_get_cursor(). See man:sd_journal_get_cursor(3).");
761 static PyObject* Reader_get_cursor(Reader *self, PyObject *args)
763 char _cleanup_free_ *cursor = NULL;
769 r = sd_journal_get_cursor(self->j, &cursor);
770 if (set_error(r, NULL, NULL))
773 return unicode_FromString(cursor);
777 PyDoc_STRVAR(Reader_test_cursor__doc__,
778 "test_cursor(str) -> bool\n\n"
779 "Test whether the cursor string matches current journal entry.\n\n"
780 "Wraps sd_journal_test_cursor(). See man:sd_journal_test_cursor(3).");
781 static PyObject* Reader_test_cursor(Reader *self, PyObject *args)
789 if (!PyArg_ParseTuple(args, "s:test_cursor", &cursor))
792 r = sd_journal_test_cursor(self->j, cursor);
793 set_error(r, NULL, NULL);
797 return PyBool_FromLong(r);
800 PyDoc_STRVAR(Reader_query_unique__doc__,
801 "query_unique(field) -> a set of values\n\n"
802 "Return a set of unique values appearing in journal for the\n"
803 "given `field`. Note this does not respect any journal matches.");
804 static PyObject* Reader_query_unique(Reader *self, PyObject *args)
810 PyObject *value_set, *key, *value;
812 if (!PyArg_ParseTuple(args, "s:query_unique", &query))
815 Py_BEGIN_ALLOW_THREADS
816 r = sd_journal_query_unique(self->j, query);
818 if (set_error(r, NULL, "Invalid field name"))
821 value_set = PySet_New(0);
822 key = unicode_FromString(query);
824 SD_JOURNAL_FOREACH_UNIQUE(self->j, uniq, uniq_len) {
825 const char *delim_ptr;
827 delim_ptr = memchr(uniq, '=', uniq_len);
828 value = PyBytes_FromStringAndSize(
830 (const char*) uniq + uniq_len - (delim_ptr + 1));
831 PySet_Add(value_set, value);
839 PyDoc_STRVAR(Reader_get_catalog__doc__,
840 "get_catalog() -> str\n\n"
841 "Retrieve a message catalog entry for the current journal entry.\n"
842 "Will throw IndexError if the entry has no MESSAGE_ID\n"
843 "and KeyError is the id is specified, but hasn't been found\n"
844 "in the catalog.\n\n"
845 "Wraps man:sd_journal_get_catalog(3).");
846 static PyObject* Reader_get_catalog(Reader *self, PyObject *args)
849 char _cleanup_free_ *msg = NULL;
854 Py_BEGIN_ALLOW_THREADS
855 r = sd_journal_get_catalog(self->j, &msg);
861 r = sd_journal_get_data(self->j, "MESSAGE_ID", &mid, &mid_len);
863 const int l = sizeof("MESSAGE_ID");
865 PyErr_Format(PyExc_KeyError, "%.*s", (int) mid_len - l,
866 (const char*) mid + l);
867 } else if (r == -ENOENT)
868 PyErr_SetString(PyExc_IndexError, "no MESSAGE_ID field");
870 set_error(r, NULL, NULL);
872 } else if (set_error(r, NULL, NULL))
875 return unicode_FromString(msg);
879 PyDoc_STRVAR(get_catalog__doc__,
880 "get_catalog(id128) -> str\n\n"
881 "Retrieve a message catalog entry for the given id.\n"
882 "Wraps man:sd_journal_get_catalog_for_message_id(3).");
883 static PyObject* get_catalog(PyObject *self, PyObject *args)
888 char _cleanup_free_ *msg = NULL;
893 if (!PyArg_ParseTuple(args, "z:get_catalog", &id_))
896 r = sd_id128_from_string(id_, &id);
897 if (set_error(r, NULL, "Invalid id128"))
900 Py_BEGIN_ALLOW_THREADS
901 r = sd_journal_get_catalog_for_message_id(id, &msg);
903 if (set_error(r, NULL, NULL))
906 return unicode_FromString(msg);
910 PyDoc_STRVAR(data_threshold__doc__,
911 "Threshold for field size truncation in bytes.\n\n"
912 "Fields longer than this will be truncated to the threshold size.\n"
913 "Defaults to 64Kb.");
915 static PyObject* Reader_get_data_threshold(Reader *self, void *closure)
920 r = sd_journal_get_data_threshold(self->j, &cvalue);
921 if (set_error(r, NULL, NULL))
924 return long_FromSize_t(cvalue);
927 static int Reader_set_data_threshold(Reader *self, PyObject *value, void *closure)
931 PyErr_SetString(PyExc_AttributeError, "Cannot delete data threshold");
934 if (!long_Check(value)){
935 PyErr_SetString(PyExc_TypeError, "Data threshold must be an int");
938 r = sd_journal_set_data_threshold(self->j, (size_t) long_AsLong(value));
939 return set_error(r, NULL, NULL);
943 PyDoc_STRVAR(closed__doc__,
944 "True iff journal is closed");
945 static PyObject* Reader_get_closed(Reader *self, void *closure)
947 return PyBool_FromLong(self->j == NULL);
951 static PyGetSetDef Reader_getsetters[] = {
952 {(char*) "data_threshold",
953 (getter) Reader_get_data_threshold,
954 (setter) Reader_set_data_threshold,
955 (char*) data_threshold__doc__,
958 (getter) Reader_get_closed,
960 (char*) closed__doc__,
965 static PyMethodDef Reader_methods[] = {
966 {"fileno", (PyCFunction) Reader_fileno, METH_NOARGS, Reader_fileno__doc__},
967 {"reliable_fd", (PyCFunction) Reader_reliable_fd, METH_NOARGS, Reader_reliable_fd__doc__},
968 {"get_events", (PyCFunction) Reader_get_events, METH_NOARGS, Reader_get_events__doc__},
969 {"get_timeout", (PyCFunction) Reader_get_timeout, METH_NOARGS, Reader_get_timeout__doc__},
970 {"get_timeout_ms", (PyCFunction) Reader_get_timeout_ms, METH_NOARGS, Reader_get_timeout_ms__doc__},
971 {"close", (PyCFunction) Reader_close, METH_NOARGS, Reader_close__doc__},
972 {"get_usage", (PyCFunction) Reader_get_usage, METH_NOARGS, Reader_get_usage__doc__},
973 {"__enter__", (PyCFunction) Reader___enter__, METH_NOARGS, Reader___enter____doc__},
974 {"__exit__", (PyCFunction) Reader___exit__, METH_VARARGS, Reader___exit____doc__},
975 {"_next", (PyCFunction) Reader_next, METH_VARARGS, Reader_next__doc__},
976 {"_previous", (PyCFunction) Reader_previous, METH_VARARGS, Reader_previous__doc__},
977 {"_get", (PyCFunction) Reader_get, METH_VARARGS, Reader_get__doc__},
978 {"_get_all", (PyCFunction) Reader_get_all, METH_NOARGS, Reader_get_all__doc__},
979 {"_get_realtime", (PyCFunction) Reader_get_realtime, METH_NOARGS, Reader_get_realtime__doc__},
980 {"_get_monotonic", (PyCFunction) Reader_get_monotonic, METH_NOARGS, Reader_get_monotonic__doc__},
981 {"add_match", (PyCFunction) Reader_add_match, METH_VARARGS|METH_KEYWORDS, Reader_add_match__doc__},
982 {"add_disjunction", (PyCFunction) Reader_add_disjunction, METH_NOARGS, Reader_add_disjunction__doc__},
983 {"flush_matches", (PyCFunction) Reader_flush_matches, METH_NOARGS, Reader_flush_matches__doc__},
984 {"seek_head", (PyCFunction) Reader_seek_head, METH_NOARGS, Reader_seek_head__doc__},
985 {"seek_tail", (PyCFunction) Reader_seek_tail, METH_NOARGS, Reader_seek_tail__doc__},
986 {"seek_realtime", (PyCFunction) Reader_seek_realtime, METH_VARARGS, Reader_seek_realtime__doc__},
987 {"seek_monotonic", (PyCFunction) Reader_seek_monotonic, METH_VARARGS, Reader_seek_monotonic__doc__},
988 {"process", (PyCFunction) Reader_process, METH_NOARGS, Reader_process__doc__},
989 {"wait", (PyCFunction) Reader_wait, METH_VARARGS, Reader_wait__doc__},
990 {"seek_cursor", (PyCFunction) Reader_seek_cursor, METH_VARARGS, Reader_seek_cursor__doc__},
991 {"_get_cursor", (PyCFunction) Reader_get_cursor, METH_NOARGS, Reader_get_cursor__doc__},
992 {"test_cursor", (PyCFunction) Reader_test_cursor, METH_VARARGS, Reader_test_cursor__doc__},
993 {"query_unique", (PyCFunction) Reader_query_unique, METH_VARARGS, Reader_query_unique__doc__},
994 {"get_catalog", (PyCFunction) Reader_get_catalog, METH_NOARGS, Reader_get_catalog__doc__},
998 static PyTypeObject ReaderType = {
999 PyVarObject_HEAD_INIT(NULL, 0)
1000 "_reader._Reader", /*tp_name*/
1001 sizeof(Reader), /*tp_basicsize*/
1003 (destructor)Reader_dealloc, /*tp_dealloc*/
1010 0, /*tp_as_sequence*/
1011 0, /*tp_as_mapping*/
1018 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
1019 Reader__doc__, /* tp_doc */
1020 0, /* tp_traverse */
1022 0, /* tp_richcompare */
1023 0, /* tp_weaklistoffset */
1025 0, /* tp_iternext */
1026 Reader_methods, /* tp_methods */
1028 Reader_getsetters, /* tp_getset */
1031 0, /* tp_descr_get */
1032 0, /* tp_descr_set */
1033 0, /* tp_dictoffset */
1034 (initproc) Reader_init, /* tp_init */
1036 PyType_GenericNew, /* tp_new */
1039 static PyMethodDef methods[] = {
1040 { "_get_catalog", get_catalog, METH_VARARGS, get_catalog__doc__},
1041 { NULL, NULL, 0, NULL } /* Sentinel */
1044 #if PY_MAJOR_VERSION >= 3
1045 static PyModuleDef module = {
1046 PyModuleDef_HEAD_INIT,
1051 NULL, NULL, NULL, NULL
1055 #if PY_MAJOR_VERSION >= 3
1056 static bool initialized = false;
1059 #pragma GCC diagnostic push
1060 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
1063 #if PY_MAJOR_VERSION >= 3
1064 PyInit__reader(void)
1073 if (PyType_Ready(&ReaderType) < 0)
1074 #if PY_MAJOR_VERSION >= 3
1080 #if PY_MAJOR_VERSION >= 3
1081 m = PyModule_Create(&module);
1086 PyStructSequence_InitType(&MonotonicType, &Monotonic_desc);
1090 m = Py_InitModule3("_reader", methods, module__doc__);
1095 Py_INCREF(&ReaderType);
1096 #if PY_MAJOR_VERSION >= 3
1097 Py_INCREF(&MonotonicType);
1099 if (PyModule_AddObject(m, "_Reader", (PyObject *) &ReaderType) ||
1100 #if PY_MAJOR_VERSION >= 3
1101 PyModule_AddObject(m, "Monotonic", (PyObject*) &MonotonicType) ||
1103 PyModule_AddIntConstant(m, "NOP", SD_JOURNAL_NOP) ||
1104 PyModule_AddIntConstant(m, "APPEND", SD_JOURNAL_APPEND) ||
1105 PyModule_AddIntConstant(m, "INVALIDATE", SD_JOURNAL_INVALIDATE) ||
1106 PyModule_AddIntConstant(m, "LOCAL_ONLY", SD_JOURNAL_LOCAL_ONLY) ||
1107 PyModule_AddIntConstant(m, "RUNTIME_ONLY", SD_JOURNAL_RUNTIME_ONLY) ||
1108 PyModule_AddIntConstant(m, "SYSTEM_ONLY", SD_JOURNAL_SYSTEM_ONLY)) {
1109 #if PY_MAJOR_VERSION >= 3
1115 #if PY_MAJOR_VERSION >= 3
1120 #pragma GCC diagnostic pop