chiark / gitweb /
systemd-python: return both parts of sd_journal_get_monotonic_usec
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sat, 23 Feb 2013 00:11:36 +0000 (01:11 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 1 Mar 2013 01:04:17 +0000 (20:04 -0500)
In Python 3, a named tuple is used. In Python 2, a simple
tuple is used. In either case, the pair is (timestamp, bootid).

src/python-systemd/_reader.c
src/python-systemd/docs/journal.rst
src/python-systemd/journal.py

index 9262c89..7645cb9 100644 (file)
@@ -67,6 +67,26 @@ static int set_error(int r, const char* path, const char* invalid_message) {
     return 1;
 }
 
+#if PY_MAJOR_VERSION >= 3
+static PyTypeObject MonotonicType;
+
+PyDoc_STRVAR(MonotonicType__doc__,
+             "A tuple of (timestamp, bootid) for holding monotonic timestamps");
+
+static PyStructSequence_Field MonotonicType_fields[] = {
+    {(char*) "timestamp", (char*) "Time"},
+    {(char*) "bootid", (char*) "Unique identifier of the boot"},
+    {NULL, NULL}
+};
+
+static PyStructSequence_Desc Monotonic_desc = {
+    (char*) "journal.Monotonic",
+    MonotonicType__doc__,
+    MonotonicType_fields,
+    2,
+};
+#endif
+
 static void Journal_dealloc(Journal* self)
 {
     sd_journal_close(self->j);
@@ -221,22 +241,37 @@ static PyObject* Journal_get_next(Journal *self, PyObject *args)
     }
 
     {
-        PyObject _cleanup_Py_DECREF_ *key = NULL, *value = NULL;
-        sd_id128_t sd_id;
+        PyObject _cleanup_Py_DECREF_
+            *key = NULL, *timestamp = NULL, *bytes = NULL, *value = NULL;
+        sd_id128_t id;
         uint64_t monotonic;
 
-        r = sd_journal_get_monotonic_usec(self->j, &monotonic, &sd_id);
+        r = sd_journal_get_monotonic_usec(self->j, &monotonic, &id);
         if (set_error(r, NULL, NULL))
             goto error;
 
+        assert_cc(sizeof(unsigned long long) == sizeof(monotonic));
         key = unicode_FromString("__MONOTONIC_TIMESTAMP");
-        if (!key)
+        timestamp = PyLong_FromUnsignedLongLong(monotonic);
+        bytes = PyBytes_FromStringAndSize((const char*) &id.bytes, sizeof(id.bytes));
+#if PY_MAJOR_VERSION >= 3
+        value = PyStructSequence_New(&MonotonicType);
+#else
+        value = PyTuple_New(2);
+#endif
+        if (!key || !timestamp || !bytes || !value)
             goto error;
 
-        assert_cc(sizeof(unsigned long long) == sizeof(monotonic));
-        value = PyLong_FromUnsignedLongLong(monotonic);
-        if (!value)
-            goto error;
+        Py_INCREF(timestamp);
+        Py_INCREF(bytes);
+
+#if PY_MAJOR_VERSION >= 3
+        PyStructSequence_SET_ITEM(value, 0, timestamp);
+        PyStructSequence_SET_ITEM(value, 1, bytes);
+#else
+        PyTuple_SET_ITEM(value, 0, timestamp);
+        PyTuple_SET_ITEM(value, 1, bytes);
+#endif
 
         if (PyDict_SetItem(dict, key, value))
             goto error;
@@ -421,7 +456,7 @@ static PyObject* Journal_seek_monotonic(Journal *self, PyObject *args)
     double timedouble;
     char *bootid = NULL;
     uint64_t timestamp;
-    sd_id128_t sd_id;
+    sd_id128_t id;
     int r;
 
     if (!PyArg_ParseTuple(args, "d|z", &timedouble, &bootid))
@@ -435,19 +470,19 @@ static PyObject* Journal_seek_monotonic(Journal *self, PyObject *args)
     }
 
     if (bootid) {
-        r = sd_id128_from_string(bootid, &sd_id);
+        r = sd_id128_from_string(bootid, &id);
         if (set_error(r, NULL, "Invalid bootid"))
             return NULL;
     } else {
         Py_BEGIN_ALLOW_THREADS
-        r = sd_id128_get_boot(&sd_id);
+        r = sd_id128_get_boot(&id);
         Py_END_ALLOW_THREADS
         if (set_error(r, NULL, NULL))
             return NULL;
     }
 
     Py_BEGIN_ALLOW_THREADS
-    r = sd_journal_seek_monotonic_usec(self->j, sd_id, timestamp);
+    r = sd_journal_seek_monotonic_usec(self->j, id, timestamp);
     Py_END_ALLOW_THREADS
     if (set_error(r, NULL, NULL))
         return NULL;
@@ -671,6 +706,10 @@ static PyModuleDef _reader_module = {
 };
 #endif
 
+#if PY_MAJOR_VERSION >= 3
+static bool initialized = false;
+#endif
+
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
 
@@ -696,6 +735,11 @@ init_reader(void)
     m = PyModule_Create(&_reader_module);
     if (m == NULL)
         return NULL;
+
+    if (!initialized) {
+        PyStructSequence_InitType(&MonotonicType, &Monotonic_desc);
+        initialized = true;
+    }
 #else
     m = Py_InitModule3("_reader", NULL, SUMMARY);
     if (m == NULL)
@@ -703,7 +747,13 @@ init_reader(void)
 #endif
 
     Py_INCREF(&JournalType);
+#if PY_MAJOR_VERSION >= 3
+    Py_INCREF(&MonotonicType);
+#endif
     if (PyModule_AddObject(m, "_Journal", (PyObject *) &JournalType) ||
+#if PY_MAJOR_VERSION >= 3
+        PyModule_AddObject(m, "Monotonic", (PyObject*) &MonotonicType) ||
+#endif
         PyModule_AddIntConstant(m, "NOP", SD_JOURNAL_NOP) ||
         PyModule_AddIntConstant(m, "APPEND", SD_JOURNAL_APPEND) ||
         PyModule_AddIntConstant(m, "INVALIDATE", SD_JOURNAL_INVALIDATE) ||
index 9d627ce..38ab57e 100644 (file)
@@ -23,6 +23,8 @@ Accessing the Journal
 
    .. automethod:: __init__
 
+.. autoclass:: Monotonic
+
 .. autoattribute:: systemd.journal.DEFAULT_CONVERTERS
 
 Whence constants
index d94934c..a5641e9 100644 (file)
@@ -38,7 +38,13 @@ from ._reader import (_Journal, NOP, APPEND, INVALIDATE,
                       LOCAL_ONLY, RUNTIME_ONLY, SYSTEM_ONLY)
 from . import id128 as _id128
 
-_MONOTONIC_CONVERTER = lambda x: _datetime.timedelta(microseconds=x)
+if _sys.version_info >= (3,):
+    from ._reader import Monotonic
+else:
+    Monotonic = tuple
+
+_MONOTONIC_CONVERTER = lambda p: Monotonic((_datetime.timedelta(microseconds=p[0]),
+                                            _uuid.UUID(bytes=p[1])))
 _REALTIME_CONVERTER = lambda x: _datetime.datetime.fromtimestamp(x / 1E6)
 DEFAULT_CONVERTERS = {
     'MESSAGE_ID': _uuid.UUID,