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;
42 PyDoc_STRVAR(module__doc__,
43 "Class to reads the systemd journal similar to journalctl.");
46 #if PY_MAJOR_VERSION >= 3
47 static PyTypeObject MonotonicType;
49 PyDoc_STRVAR(MonotonicType__doc__,
50 "A tuple of (timestamp, bootid) for holding monotonic timestamps");
52 static PyStructSequence_Field MonotonicType_fields[] = {
53 {(char*) "timestamp", (char*) "Time"},
54 {(char*) "bootid", (char*) "Unique identifier of the boot"},
58 static PyStructSequence_Desc Monotonic_desc = {
59 (char*) "journal.Monotonic",
67 static void Reader_dealloc(Reader* self)
69 sd_journal_close(self->j);
70 Py_TYPE(self)->tp_free((PyObject*)self);
73 PyDoc_STRVAR(Reader__doc__,
74 "_Reader([flags | path]) -> ...\n\n"
75 "_Reader allows filtering and retrieval of Journal entries.\n"
76 "Note: this is a low-level interface, and probably not what you\n"
77 "want, use systemd.journal.Reader instead.\n\n"
78 "Argument `flags` sets open flags of the journal, which can be one\n"
79 "of, or ORed combination of constants: LOCAL_ONLY (default) opens\n"
80 "journal on local machine only; RUNTIME_ONLY opens only\n"
81 "volatile journal files; and SYSTEM_ONLY opens only\n"
82 "journal files of system services and the kernel.\n\n"
83 "Argument `path` is the directory of journal files. Note that\n"
84 "`flags` and `path` are exclusive.\n\n"
85 "_Reader implements the context manager protocol: the journal\n"
86 "will be closed when exiting the block.");
87 static int Reader_init(Reader *self, PyObject *args, PyObject *keywds)
92 static const char* const kwlist[] = {"flags", "path", NULL};
93 if (!PyArg_ParseTupleAndKeywords(args, keywds, "|iz", (char**) kwlist,
98 flags = SD_JOURNAL_LOCAL_ONLY;
101 PyErr_SetString(PyExc_ValueError, "cannot use both flags and path");
105 Py_BEGIN_ALLOW_THREADS
107 r = sd_journal_open_directory(&self->j, path, 0);
109 r = sd_journal_open(&self->j, flags);
112 return set_error(r, path, "Invalid flags or path");
116 PyDoc_STRVAR(Reader_fileno__doc__,
117 "fileno() -> int\n\n"
118 "Get a file descriptor to poll for changes in the journal.\n"
119 "This method invokes sd_journal_get_fd().\n"
120 "See man:sd_journal_get_fd(3).");
121 static PyObject* Reader_fileno(Reader *self, PyObject *args)
123 int fd = sd_journal_get_fd(self->j);
124 set_error(fd, NULL, NULL);
127 return long_FromLong(fd);
131 PyDoc_STRVAR(Reader_reliable_fd__doc__,
132 "reliable_fd() -> bool\n\n"
133 "Returns True iff the journal can be polled reliably.\n"
134 "This method invokes sd_journal_reliable_fd().\n"
135 "See man:sd_journal_reliable_fd(3).");
136 static PyObject* Reader_reliable_fd(Reader *self, PyObject *args)
138 int r = sd_journal_reliable_fd(self->j);
139 set_error(r, NULL, NULL);
142 return PyBool_FromLong(r);
146 PyDoc_STRVAR(Reader_get_events__doc__,
147 "get_events() -> int\n\n"
148 "Returns a mask of poll() events to wait for on the file\n"
149 "descriptor returned by .fileno().\n\n"
150 "See man:sd_journal_get_events(3) for further discussion.");
151 static PyObject* Reader_get_events(Reader *self, PyObject *args)
153 int r = sd_journal_get_events(self->j);
154 set_error(r, NULL, NULL);
157 return long_FromLong(r);
161 PyDoc_STRVAR(Reader_get_timeout__doc__,
162 "get_timeout() -> int or None\n\n"
163 "Returns a timeout value for usage in poll(), the time since the\n"
164 "epoch of clock_gettime(2) in microseconds, or None if no timeout\n"
166 "The return value must be converted to a relative timeout in\n"
167 "milliseconds if it is to be used as an argument for poll().\n"
168 "See man:sd_journal_get_timeout(3) for further discussion.");
169 static PyObject* Reader_get_timeout(Reader *self, PyObject *args)
174 r = sd_journal_get_timeout(self->j, &t);
175 set_error(r, NULL, NULL);
179 if (t == (uint64_t) -1)
182 assert_cc(sizeof(unsigned long long) == sizeof(t));
183 return PyLong_FromUnsignedLongLong(t);
187 PyDoc_STRVAR(Reader_get_timeout_ms__doc__,
188 "get_timeout_ms() -> int\n\n"
189 "Returns a timeout value suitable for usage in poll(), the value\n"
190 "returned by .get_timeout() converted to relative ms, or -1 if\n"
191 "no timeout is necessary.");
192 static PyObject* Reader_get_timeout_ms(Reader *self, PyObject *args)
197 r = sd_journal_get_timeout(self->j, &t);
198 set_error(r, NULL, NULL);
202 return absolute_timeout(t);
206 PyDoc_STRVAR(Reader_close__doc__,
207 "close() -> None\n\n"
208 "Free resources allocated by this Reader object.\n"
209 "This method invokes sd_journal_close().\n"
210 "See man:sd_journal_close(3).");
211 static PyObject* Reader_close(Reader *self, PyObject *args)
216 sd_journal_close(self->j);
222 PyDoc_STRVAR(Reader_get_usage__doc__,
223 "get_usage() -> int\n\n"
224 "Returns the total disk space currently used by journal\n"
225 "files (in bytes). If `SD_JOURNAL_LOCAL_ONLY` was\n"
226 "passed when opening the journal this value will only reflect\n"
227 "the size of journal files of the local host, otherwise\n"
229 "This method invokes sd_journal_get_usage().\n"
230 "See man:sd_journal_get_usage(3).");
231 static PyObject* Reader_get_usage(Reader *self, PyObject *args)
236 r = sd_journal_get_usage(self->j, &bytes);
237 if (set_error(r, NULL, NULL))
240 assert_cc(sizeof(unsigned long long) == sizeof(bytes));
241 return PyLong_FromUnsignedLongLong(bytes);
245 PyDoc_STRVAR(Reader___enter____doc__,
246 "__enter__() -> self\n\n"
247 "Part of the context manager protocol.\n"
249 static PyObject* Reader___enter__(PyObject *self, PyObject *args)
258 PyDoc_STRVAR(Reader___exit____doc__,
259 "__exit__(type, value, traceback) -> None\n\n"
260 "Part of the context manager protocol.\n"
261 "Closes the journal.\n");
262 static PyObject* Reader___exit__(Reader *self, PyObject *args)
264 return Reader_close(self, args);
268 PyDoc_STRVAR(Reader_next__doc__,
269 "next([skip]) -> bool\n\n"
270 "Go to the next log entry. Optional skip value means to go to\n"
271 "the `skip`\\-th log entry.\n"
272 "Returns False if at end of file, True otherwise.");
273 static PyObject* Reader_next(Reader *self, PyObject *args)
278 if (!PyArg_ParseTuple(args, "|L:next", &skip))
282 PyErr_SetString(PyExc_ValueError, "skip must be nonzero");
286 Py_BEGIN_ALLOW_THREADS
288 r = sd_journal_next(self->j);
289 else if (skip == -1LL)
290 r = sd_journal_previous(self->j);
292 r = sd_journal_next_skip(self->j, skip);
293 else if (skip < -1LL)
294 r = sd_journal_previous_skip(self->j, -skip);
296 assert_not_reached("should not be here");
299 set_error(r, NULL, NULL);
302 return PyBool_FromLong(r);
305 PyDoc_STRVAR(Reader_previous__doc__,
306 "previous([skip]) -> bool\n\n"
307 "Go to the previous log entry. Optional skip value means to \n"
308 "go to the `skip`\\-th previous log entry.\n"
309 "Returns False if at start of file, True otherwise.");
310 static PyObject* Reader_previous(Reader *self, PyObject *args)
313 if (!PyArg_ParseTuple(args, "|L:previous", &skip))
316 return PyObject_CallMethod((PyObject *)self, (char*) "_next",
321 static int extract(const char* msg, size_t msg_len,
322 PyObject **key, PyObject **value) {
323 PyObject *k = NULL, *v;
324 const char *delim_ptr;
326 delim_ptr = memchr(msg, '=', msg_len);
328 PyErr_SetString(PyExc_OSError,
329 "journal gave us a field without '='");
334 k = unicode_FromStringAndSize(msg, delim_ptr - (const char*) msg);
340 v = PyBytes_FromStringAndSize(delim_ptr + 1,
341 (const char*) msg + msg_len - (delim_ptr + 1));
356 PyDoc_STRVAR(Reader_get__doc__,
357 "get(str) -> str\n\n"
358 "Return data associated with this key in current log entry.\n"
359 "Throws KeyError is the data is not available.");
360 static PyObject* Reader_get(Reader *self, PyObject *args)
371 if (!PyArg_ParseTuple(args, "s:get", &field))
374 r = sd_journal_get_data(self->j, field, &msg, &msg_len);
376 PyErr_SetString(PyExc_KeyError, field);
378 } else if (set_error(r, NULL, "field name is not valid"))
381 r = extract(msg, msg_len, NULL, &value);
388 PyDoc_STRVAR(Reader_get_all__doc__,
389 "_get_all() -> dict\n\n"
390 "Return dictionary of the current log entry.");
391 static PyObject* Reader_get_all(Reader *self, PyObject *args)
402 SD_JOURNAL_FOREACH_DATA(self->j, msg, msg_len) {
403 _cleanup_Py_DECREF_ PyObject *key = NULL, *value = NULL;
405 r = extract(msg, msg_len, &key, &value);
409 if (PyDict_Contains(dict, key)) {
410 PyObject *cur_value = PyDict_GetItem(dict, key);
412 if (PyList_CheckExact(cur_value)) {
413 r = PyList_Append(cur_value, value);
417 _cleanup_Py_DECREF_ PyObject *tmp_list = PyList_New(0);
421 r = PyList_Append(tmp_list, cur_value);
425 r = PyList_Append(tmp_list, value);
429 r = PyDict_SetItem(dict, key, tmp_list);
434 r = PyDict_SetItem(dict, key, value);
448 PyDoc_STRVAR(Reader_get_realtime__doc__,
449 "get_realtime() -> int\n\n"
450 "Return the realtime timestamp for the current journal entry\n"
451 "in microseconds.\n\n"
452 "Wraps sd_journal_get_realtime_usec().\n"
453 "See man:sd_journal_get_realtime_usec(3).");
454 static PyObject* Reader_get_realtime(Reader *self, PyObject *args)
462 r = sd_journal_get_realtime_usec(self->j, ×tamp);
463 if (set_error(r, NULL, NULL))
466 assert_cc(sizeof(unsigned long long) == sizeof(timestamp));
467 return PyLong_FromUnsignedLongLong(timestamp);
471 PyDoc_STRVAR(Reader_get_monotonic__doc__,
472 "get_monotonic() -> (timestamp, bootid)\n\n"
473 "Return the monotonic timestamp for the current journal entry\n"
474 "as a tuple of time in microseconds and bootid.\n\n"
475 "Wraps sd_journal_get_monotonic_usec().\n"
476 "See man:sd_journal_get_monotonic_usec(3).");
477 static PyObject* Reader_get_monotonic(Reader *self, PyObject *args)
481 PyObject *monotonic, *bootid, *tuple;
487 r = sd_journal_get_monotonic_usec(self->j, ×tamp, &id);
488 if (set_error(r, NULL, NULL))
491 assert_cc(sizeof(unsigned long long) == sizeof(timestamp));
492 monotonic = PyLong_FromUnsignedLongLong(timestamp);
493 bootid = PyBytes_FromStringAndSize((const char*) &id.bytes, sizeof(id.bytes));
494 #if PY_MAJOR_VERSION >= 3
495 tuple = PyStructSequence_New(&MonotonicType);
497 tuple = PyTuple_New(2);
499 if (!monotonic || !bootid || !tuple) {
500 Py_XDECREF(monotonic);
506 #if PY_MAJOR_VERSION >= 3
507 PyStructSequence_SET_ITEM(tuple, 0, monotonic);
508 PyStructSequence_SET_ITEM(tuple, 1, bootid);
510 PyTuple_SET_ITEM(tuple, 0, monotonic);
511 PyTuple_SET_ITEM(tuple, 1, bootid);
517 PyDoc_STRVAR(Reader_add_match__doc__,
518 "add_match(match) -> None\n\n"
519 "Add a match to filter journal log entries. All matches of different\n"
520 "fields are combined with logical AND, and matches of the same field\n"
521 "are automatically combined with logical OR.\n"
522 "Match is a string of the form \"FIELD=value\".");
523 static PyObject* Reader_add_match(Reader *self, PyObject *args, PyObject *keywds)
527 if (!PyArg_ParseTuple(args, "s#:add_match", &match, &match_len))
530 r = sd_journal_add_match(self->j, match, match_len);
531 set_error(r, NULL, "Invalid match");
539 PyDoc_STRVAR(Reader_add_disjunction__doc__,
540 "add_disjunction() -> None\n\n"
541 "Inserts a logical OR between matches added since previous\n"
542 "add_disjunction() or add_conjunction() and the next\n"
543 "add_disjunction() or add_conjunction().\n\n"
544 "See man:sd_journal_add_disjunction(3) for explanation.");
545 static PyObject* Reader_add_disjunction(Reader *self, PyObject *args)
548 r = sd_journal_add_disjunction(self->j);
549 set_error(r, NULL, NULL);
556 PyDoc_STRVAR(Reader_add_conjunction__doc__,
557 "add_conjunction() -> None\n\n"
558 "Inserts a logical AND between matches added since previous\n"
559 "add_disjunction() or add_conjunction() and the next\n"
560 "add_disjunction() or add_conjunction().\n\n"
561 "See man:sd_journal_add_disjunction(3) for explanation.");
562 static PyObject* Reader_add_conjunction(Reader *self, PyObject *args)
565 r = sd_journal_add_conjunction(self->j);
566 set_error(r, NULL, NULL);
573 PyDoc_STRVAR(Reader_flush_matches__doc__,
574 "flush_matches() -> None\n\n"
575 "Clear all current match filters.");
576 static PyObject* Reader_flush_matches(Reader *self, PyObject *args)
578 sd_journal_flush_matches(self->j);
583 PyDoc_STRVAR(Reader_seek_head__doc__,
584 "seek_head() -> None\n\n"
585 "Jump to the beginning of the journal.\n"
586 "This method invokes sd_journal_seek_head().\n"
587 "See man:sd_journal_seek_head(3).");
588 static PyObject* Reader_seek_head(Reader *self, PyObject *args)
591 Py_BEGIN_ALLOW_THREADS
592 r = sd_journal_seek_head(self->j);
594 if (set_error(r, NULL, NULL))
600 PyDoc_STRVAR(Reader_seek_tail__doc__,
601 "seek_tail() -> None\n\n"
602 "Jump to the end of the journal.\n"
603 "This method invokes sd_journal_seek_tail().\n"
604 "See man:sd_journal_seek_tail(3).");
605 static PyObject* Reader_seek_tail(Reader *self, PyObject *args)
608 Py_BEGIN_ALLOW_THREADS
609 r = sd_journal_seek_tail(self->j);
611 if (set_error(r, NULL, NULL))
617 PyDoc_STRVAR(Reader_seek_realtime__doc__,
618 "seek_realtime(realtime) -> None\n\n"
619 "Seek to nearest matching journal entry to `realtime`. Argument\n"
620 "`realtime` in specified in seconds.");
621 static PyObject* Reader_seek_realtime(Reader *self, PyObject *args)
626 if (!PyArg_ParseTuple(args, "K:seek_realtime", ×tamp))
629 Py_BEGIN_ALLOW_THREADS
630 r = sd_journal_seek_realtime_usec(self->j, timestamp);
632 if (set_error(r, NULL, NULL))
638 PyDoc_STRVAR(Reader_seek_monotonic__doc__,
639 "seek_monotonic(monotonic[, bootid]) -> None\n\n"
640 "Seek to nearest matching journal entry to `monotonic`. Argument\n"
641 "`monotonic` is an timestamp from boot in microseconds.\n"
642 "Argument `bootid` is a string representing which boot the\n"
643 "monotonic time is reference to. Defaults to current bootid.");
644 static PyObject* Reader_seek_monotonic(Reader *self, PyObject *args)
651 if (!PyArg_ParseTuple(args, "K|z:seek_monotonic", ×tamp, &bootid))
655 r = sd_id128_from_string(bootid, &id);
656 if (set_error(r, NULL, "Invalid bootid"))
659 Py_BEGIN_ALLOW_THREADS
660 r = sd_id128_get_boot(&id);
662 if (set_error(r, NULL, NULL))
666 Py_BEGIN_ALLOW_THREADS
667 r = sd_journal_seek_monotonic_usec(self->j, id, timestamp);
669 if (set_error(r, NULL, NULL))
676 PyDoc_STRVAR(Reader_process__doc__,
677 "process() -> state change (integer)\n\n"
678 "Process events and reset the readable state of the file\n"
679 "descriptor returned by .fileno().\n\n"
680 "Will return constants: NOP if no change; APPEND if new\n"
681 "entries have been added to the end of the journal; and\n"
682 "INVALIDATE if journal files have been added or removed.\n\n"
683 "See man:sd_journal_process(3) for further discussion.");
684 static PyObject* Reader_process(Reader *self, PyObject *args)
690 Py_BEGIN_ALLOW_THREADS
691 r = sd_journal_process(self->j);
693 if (set_error(r, NULL, NULL) < 0)
696 return long_FromLong(r);
700 PyDoc_STRVAR(Reader_wait__doc__,
701 "wait([timeout]) -> state change (integer)\n\n"
702 "Wait for a change in the journal. Argument `timeout` specifies\n"
703 "the maximum number of microseconds to wait before returning\n"
704 "regardless of wheter the journal has changed. If `timeout` is -1,\n"
705 "then block forever.\n\n"
706 "Will return constants: NOP if no change; APPEND if new\n"
707 "entries have been added to the end of the journal; and\n"
708 "INVALIDATE if journal files have been added or removed.\n\n"
709 "See man:sd_journal_wait(3) for further discussion.");
710 static PyObject* Reader_wait(Reader *self, PyObject *args)
715 if (!PyArg_ParseTuple(args, "|L:wait", &timeout))
718 Py_BEGIN_ALLOW_THREADS
719 r = sd_journal_wait(self->j, timeout);
721 if (set_error(r, NULL, NULL) < 0)
724 return long_FromLong(r);
728 PyDoc_STRVAR(Reader_seek_cursor__doc__,
729 "seek_cursor(cursor) -> None\n\n"
730 "Seek to journal entry by given unique reference `cursor`.");
731 static PyObject* Reader_seek_cursor(Reader *self, PyObject *args)
736 if (!PyArg_ParseTuple(args, "s:seek_cursor", &cursor))
739 Py_BEGIN_ALLOW_THREADS
740 r = sd_journal_seek_cursor(self->j, cursor);
742 if (set_error(r, NULL, "Invalid cursor"))
748 PyDoc_STRVAR(Reader_get_cursor__doc__,
749 "get_cursor() -> str\n\n"
750 "Return a cursor string for the current journal entry.\n\n"
751 "Wraps sd_journal_get_cursor(). See man:sd_journal_get_cursor(3).");
752 static PyObject* Reader_get_cursor(Reader *self, PyObject *args)
754 _cleanup_free_ char *cursor = NULL;
760 r = sd_journal_get_cursor(self->j, &cursor);
761 if (set_error(r, NULL, NULL))
764 return unicode_FromString(cursor);
768 PyDoc_STRVAR(Reader_test_cursor__doc__,
769 "test_cursor(str) -> bool\n\n"
770 "Test whether the cursor string matches current journal entry.\n\n"
771 "Wraps sd_journal_test_cursor(). See man:sd_journal_test_cursor(3).");
772 static PyObject* Reader_test_cursor(Reader *self, PyObject *args)
780 if (!PyArg_ParseTuple(args, "s:test_cursor", &cursor))
783 r = sd_journal_test_cursor(self->j, cursor);
784 set_error(r, NULL, NULL);
788 return PyBool_FromLong(r);
791 PyDoc_STRVAR(Reader_query_unique__doc__,
792 "query_unique(field) -> a set of values\n\n"
793 "Return a set of unique values appearing in journal for the\n"
794 "given `field`. Note this does not respect any journal matches.");
795 static PyObject* Reader_query_unique(Reader *self, PyObject *args)
801 PyObject *value_set, *key, *value;
803 if (!PyArg_ParseTuple(args, "s:query_unique", &query))
806 Py_BEGIN_ALLOW_THREADS
807 r = sd_journal_query_unique(self->j, query);
809 if (set_error(r, NULL, "Invalid field name"))
812 value_set = PySet_New(0);
813 key = unicode_FromString(query);
815 SD_JOURNAL_FOREACH_UNIQUE(self->j, uniq, uniq_len) {
816 const char *delim_ptr;
818 delim_ptr = memchr(uniq, '=', uniq_len);
819 value = PyBytes_FromStringAndSize(
821 (const char*) uniq + uniq_len - (delim_ptr + 1));
822 PySet_Add(value_set, value);
830 PyDoc_STRVAR(Reader_get_catalog__doc__,
831 "get_catalog() -> str\n\n"
832 "Retrieve a message catalog entry for the current journal entry.\n"
833 "Will throw IndexError if the entry has no MESSAGE_ID\n"
834 "and KeyError is the id is specified, but hasn't been found\n"
835 "in the catalog.\n\n"
836 "Wraps man:sd_journal_get_catalog(3).");
837 static PyObject* Reader_get_catalog(Reader *self, PyObject *args)
840 _cleanup_free_ char *msg = NULL;
845 Py_BEGIN_ALLOW_THREADS
846 r = sd_journal_get_catalog(self->j, &msg);
852 r = sd_journal_get_data(self->j, "MESSAGE_ID", &mid, &mid_len);
854 const int l = sizeof("MESSAGE_ID");
856 PyErr_Format(PyExc_KeyError, "%.*s", (int) mid_len - l,
857 (const char*) mid + l);
858 } else if (r == -ENOENT)
859 PyErr_SetString(PyExc_IndexError, "no MESSAGE_ID field");
861 set_error(r, NULL, NULL);
863 } else if (set_error(r, NULL, NULL))
866 return unicode_FromString(msg);
870 PyDoc_STRVAR(get_catalog__doc__,
871 "get_catalog(id128) -> str\n\n"
872 "Retrieve a message catalog entry for the given id.\n"
873 "Wraps man:sd_journal_get_catalog_for_message_id(3).");
874 static PyObject* get_catalog(PyObject *self, PyObject *args)
879 _cleanup_free_ char *msg = NULL;
884 if (!PyArg_ParseTuple(args, "z:get_catalog", &id_))
887 r = sd_id128_from_string(id_, &id);
888 if (set_error(r, NULL, "Invalid id128"))
891 Py_BEGIN_ALLOW_THREADS
892 r = sd_journal_get_catalog_for_message_id(id, &msg);
894 if (set_error(r, NULL, NULL))
897 return unicode_FromString(msg);
901 PyDoc_STRVAR(data_threshold__doc__,
902 "Threshold for field size truncation in bytes.\n\n"
903 "Fields longer than this will be truncated to the threshold size.\n"
904 "Defaults to 64Kb.");
906 static PyObject* Reader_get_data_threshold(Reader *self, void *closure)
911 r = sd_journal_get_data_threshold(self->j, &cvalue);
912 if (set_error(r, NULL, NULL))
915 return long_FromSize_t(cvalue);
918 static int Reader_set_data_threshold(Reader *self, PyObject *value, void *closure)
922 PyErr_SetString(PyExc_AttributeError, "Cannot delete data threshold");
925 if (!long_Check(value)){
926 PyErr_SetString(PyExc_TypeError, "Data threshold must be an int");
929 r = sd_journal_set_data_threshold(self->j, (size_t) long_AsLong(value));
930 return set_error(r, NULL, NULL);
934 PyDoc_STRVAR(closed__doc__,
935 "True iff journal is closed");
936 static PyObject* Reader_get_closed(Reader *self, void *closure)
938 return PyBool_FromLong(self->j == NULL);
942 static PyGetSetDef Reader_getsetters[] = {
943 {(char*) "data_threshold",
944 (getter) Reader_get_data_threshold,
945 (setter) Reader_set_data_threshold,
946 (char*) data_threshold__doc__,
949 (getter) Reader_get_closed,
951 (char*) closed__doc__,
956 static PyMethodDef Reader_methods[] = {
957 {"fileno", (PyCFunction) Reader_fileno, METH_NOARGS, Reader_fileno__doc__},
958 {"reliable_fd", (PyCFunction) Reader_reliable_fd, METH_NOARGS, Reader_reliable_fd__doc__},
959 {"get_events", (PyCFunction) Reader_get_events, METH_NOARGS, Reader_get_events__doc__},
960 {"get_timeout", (PyCFunction) Reader_get_timeout, METH_NOARGS, Reader_get_timeout__doc__},
961 {"get_timeout_ms", (PyCFunction) Reader_get_timeout_ms, METH_NOARGS, Reader_get_timeout_ms__doc__},
962 {"close", (PyCFunction) Reader_close, METH_NOARGS, Reader_close__doc__},
963 {"get_usage", (PyCFunction) Reader_get_usage, METH_NOARGS, Reader_get_usage__doc__},
964 {"__enter__", (PyCFunction) Reader___enter__, METH_NOARGS, Reader___enter____doc__},
965 {"__exit__", (PyCFunction) Reader___exit__, METH_VARARGS, Reader___exit____doc__},
966 {"_next", (PyCFunction) Reader_next, METH_VARARGS, Reader_next__doc__},
967 {"_previous", (PyCFunction) Reader_previous, METH_VARARGS, Reader_previous__doc__},
968 {"_get", (PyCFunction) Reader_get, METH_VARARGS, Reader_get__doc__},
969 {"_get_all", (PyCFunction) Reader_get_all, METH_NOARGS, Reader_get_all__doc__},
970 {"_get_realtime", (PyCFunction) Reader_get_realtime, METH_NOARGS, Reader_get_realtime__doc__},
971 {"_get_monotonic", (PyCFunction) Reader_get_monotonic, METH_NOARGS, Reader_get_monotonic__doc__},
972 {"add_match", (PyCFunction) Reader_add_match, METH_VARARGS|METH_KEYWORDS, Reader_add_match__doc__},
973 {"add_disjunction", (PyCFunction) Reader_add_disjunction, METH_NOARGS, Reader_add_disjunction__doc__},
974 {"add_conjunction", (PyCFunction) Reader_add_conjunction, METH_NOARGS, Reader_add_conjunction__doc__},
975 {"flush_matches", (PyCFunction) Reader_flush_matches, METH_NOARGS, Reader_flush_matches__doc__},
976 {"seek_head", (PyCFunction) Reader_seek_head, METH_NOARGS, Reader_seek_head__doc__},
977 {"seek_tail", (PyCFunction) Reader_seek_tail, METH_NOARGS, Reader_seek_tail__doc__},
978 {"seek_realtime", (PyCFunction) Reader_seek_realtime, METH_VARARGS, Reader_seek_realtime__doc__},
979 {"seek_monotonic", (PyCFunction) Reader_seek_monotonic, METH_VARARGS, Reader_seek_monotonic__doc__},
980 {"process", (PyCFunction) Reader_process, METH_NOARGS, Reader_process__doc__},
981 {"wait", (PyCFunction) Reader_wait, METH_VARARGS, Reader_wait__doc__},
982 {"seek_cursor", (PyCFunction) Reader_seek_cursor, METH_VARARGS, Reader_seek_cursor__doc__},
983 {"_get_cursor", (PyCFunction) Reader_get_cursor, METH_NOARGS, Reader_get_cursor__doc__},
984 {"test_cursor", (PyCFunction) Reader_test_cursor, METH_VARARGS, Reader_test_cursor__doc__},
985 {"query_unique", (PyCFunction) Reader_query_unique, METH_VARARGS, Reader_query_unique__doc__},
986 {"get_catalog", (PyCFunction) Reader_get_catalog, METH_NOARGS, Reader_get_catalog__doc__},
990 static PyTypeObject ReaderType = {
991 PyVarObject_HEAD_INIT(NULL, 0)
992 "_reader._Reader", /*tp_name*/
993 sizeof(Reader), /*tp_basicsize*/
995 (destructor)Reader_dealloc, /*tp_dealloc*/
1002 0, /*tp_as_sequence*/
1003 0, /*tp_as_mapping*/
1010 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
1011 Reader__doc__, /* tp_doc */
1012 0, /* tp_traverse */
1014 0, /* tp_richcompare */
1015 0, /* tp_weaklistoffset */
1017 0, /* tp_iternext */
1018 Reader_methods, /* tp_methods */
1020 Reader_getsetters, /* tp_getset */
1023 0, /* tp_descr_get */
1024 0, /* tp_descr_set */
1025 0, /* tp_dictoffset */
1026 (initproc) Reader_init, /* tp_init */
1028 PyType_GenericNew, /* tp_new */
1031 static PyMethodDef methods[] = {
1032 { "_get_catalog", get_catalog, METH_VARARGS, get_catalog__doc__},
1033 { NULL, NULL, 0, NULL } /* Sentinel */
1036 #if PY_MAJOR_VERSION >= 3
1037 static PyModuleDef module = {
1038 PyModuleDef_HEAD_INIT,
1043 NULL, NULL, NULL, NULL
1047 #if PY_MAJOR_VERSION >= 3
1048 static bool initialized = false;
1051 #pragma GCC diagnostic push
1052 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
1055 #if PY_MAJOR_VERSION >= 3
1056 PyInit__reader(void)
1065 if (PyType_Ready(&ReaderType) < 0)
1066 #if PY_MAJOR_VERSION >= 3
1072 #if PY_MAJOR_VERSION >= 3
1073 m = PyModule_Create(&module);
1078 PyStructSequence_InitType(&MonotonicType, &Monotonic_desc);
1082 m = Py_InitModule3("_reader", methods, module__doc__);
1087 Py_INCREF(&ReaderType);
1088 #if PY_MAJOR_VERSION >= 3
1089 Py_INCREF(&MonotonicType);
1091 if (PyModule_AddObject(m, "_Reader", (PyObject *) &ReaderType) ||
1092 #if PY_MAJOR_VERSION >= 3
1093 PyModule_AddObject(m, "Monotonic", (PyObject*) &MonotonicType) ||
1095 PyModule_AddIntConstant(m, "NOP", SD_JOURNAL_NOP) ||
1096 PyModule_AddIntConstant(m, "APPEND", SD_JOURNAL_APPEND) ||
1097 PyModule_AddIntConstant(m, "INVALIDATE", SD_JOURNAL_INVALIDATE) ||
1098 PyModule_AddIntConstant(m, "LOCAL_ONLY", SD_JOURNAL_LOCAL_ONLY) ||
1099 PyModule_AddIntConstant(m, "RUNTIME_ONLY", SD_JOURNAL_RUNTIME_ONLY) ||
1100 PyModule_AddIntConstant(m, "SYSTEM", SD_JOURNAL_SYSTEM) ||
1101 PyModule_AddIntConstant(m, "SYSTEM_ONLY", SD_JOURNAL_SYSTEM_ONLY) ||
1102 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION)) {
1103 #if PY_MAJOR_VERSION >= 3
1109 #if PY_MAJOR_VERSION >= 3
1114 #pragma GCC diagnostic pop