systemd-python: cleanup up usec_t handling

The behaviour wrt. seconds vs. microseconds was inconsistent.
Now _Reader always uses native units (us), while Reader always
uses seconds and accepts both floats and ints. This way the
conversion is always done in the Python layer, and the lower
level API allows access to the journal API without the potentially
lossy conversion between double and uint64_t.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek
2013-03-21 22:39:24 -04:00
parent 50a279f857
commit 806bc1cb61
2 changed files with 28 additions and 31 deletions
+12 -27
View File
@@ -499,22 +499,15 @@ static PyObject* Reader_seek_tail(Reader *self, PyObject *args)
PyDoc_STRVAR(Reader_seek_realtime__doc__,
"seek_realtime(realtime) -> None\n\n"
"Seek to nearest matching journal entry to `realtime`. Argument\n"
"`realtime` can must be an integer unix timestamp.");
"`realtime` in specified in seconds.");
static PyObject* Reader_seek_realtime(Reader *self, PyObject *args)
{
double timedouble;
uint64_t timestamp;
int r;
if (!PyArg_ParseTuple(args, "d:_Reader.seek_realtime", &timedouble))
if (!PyArg_ParseTuple(args, "K:seek_realtime", &timestamp))
return NULL;
timestamp = (uint64_t) (timedouble * 1.0E6);
if ((int64_t) timestamp < 0LL) {
PyErr_SetString(PyExc_ValueError, "Time must be a positive integer");
return NULL;
}
Py_BEGIN_ALLOW_THREADS
r = sd_journal_seek_realtime_usec(self->j, timestamp);
Py_END_ALLOW_THREADS
@@ -527,27 +520,19 @@ static PyObject* Reader_seek_realtime(Reader *self, PyObject *args)
PyDoc_STRVAR(Reader_seek_monotonic__doc__,
"seek_monotonic(monotonic[, bootid]) -> None\n\n"
"Seek to nearest matching journal entry to `monotonic`. Argument\n"
"`monotonic` is an timestamp from boot in seconds.\n"
"`monotonic` is an timestamp from boot in microseconds.\n"
"Argument `bootid` is a string representing which boot the\n"
"monotonic time is reference to. Defaults to current bootid.");
static PyObject* Reader_seek_monotonic(Reader *self, PyObject *args)
{
double timedouble;
char *bootid = NULL;
uint64_t timestamp;
sd_id128_t id;
int r;
if (!PyArg_ParseTuple(args, "d|z:_Reader.seek_monotonic", &timedouble, &bootid))
if (!PyArg_ParseTuple(args, "K|z:seek_monotonic", &timestamp, &bootid))
return NULL;
timestamp = (uint64_t) (timedouble * 1.0E6);
if ((int64_t) timestamp < 0LL) {
PyErr_SetString(PyExc_ValueError, "Time must be positive number");
return NULL;
}
if (bootid) {
r = sd_id128_from_string(bootid, &id);
if (set_error(r, NULL, "Invalid bootid"))
@@ -565,6 +550,7 @@ static PyObject* Reader_seek_monotonic(Reader *self, PyObject *args)
Py_END_ALLOW_THREADS
if (set_error(r, NULL, NULL))
return NULL;
Py_RETURN_NONE;
}
@@ -572,23 +558,22 @@ static PyObject* Reader_seek_monotonic(Reader *self, PyObject *args)
PyDoc_STRVAR(Reader_wait__doc__,
"wait([timeout]) -> state change (integer)\n\n"
"Wait for a change in the journal. Argument `timeout` specifies\n"
"the maximum number of seconds to wait before returning\n"
"regardless of wheter the journal has changed. If `timeout` is not given\n"
"or is 0, then block forever.\n"
"the maximum number of microseconds to wait before returning\n"
"regardless of wheter the journal has changed. If `timeout` is -1,\n"
"then block forever.\n\n"
"Will return constants: NOP if no change; APPEND if new\n"
"entries have been added to the end of the journal; and\n"
"INVALIDATE if journal files have been added or removed.");
static PyObject* Reader_wait(Reader *self, PyObject *args, PyObject *keywds)
static PyObject* Reader_wait(Reader *self, PyObject *args)
{
int r;
int64_t timeout = 0LL;
int64_t timeout;
if (!PyArg_ParseTuple(args, "|L:_Reader.wait", &timeout))
if (!PyArg_ParseTuple(args, "|L:wait", &timeout))
return NULL;
Py_BEGIN_ALLOW_THREADS
r = sd_journal_wait(self->j,
timeout == 0 ? (uint64_t) -1 : timeout * 1E6);
r = sd_journal_wait(self->j, timeout);
Py_END_ALLOW_THREADS
if (set_error(r, NULL, NULL) < 0)
return NULL;
+16 -4
View File
@@ -51,10 +51,10 @@ def _convert_source_monotonic(s):
return _datetime.timedelta(microseconds=int(s))
def _convert_realtime(t):
return _datetime.datetime.fromtimestamp(t / 1E6)
return _datetime.datetime.fromtimestamp(t / 1000000)
def _convert_timestamp(s):
return _datetime.datetime.fromtimestamp(int(s) / 1E6)
return _datetime.datetime.fromtimestamp(int(s) / 1000000)
if _sys.version_info >= (3,):
def _convert_uuid(s):
@@ -209,6 +209,17 @@ class Reader(_Reader):
return set(self._convert_field(field, value)
for value in super(Reader, self).query_unique(field))
def wait(self, timeout=None):
"""Wait for a change in the journal. `timeout` is the maximum
time in seconds to wait, or None, to wait forever.
Returns one of NOP (no change), APPEND (new entries have been
added to the end of the journal), or INVALIDATE (journal files
have been added or removed).
"""
us = -1 if timeout is None else int(timeout * 1000000)
return super(Reader, self).wait(timeout)
def seek_realtime(self, realtime):
"""Seek to a matching journal entry nearest to `realtime` time.
@@ -216,8 +227,8 @@ class Reader(_Reader):
or datetime.datetime instance.
"""
if isinstance(realtime, _datetime.datetime):
realtime = float(realtime.strftime("%s.%f"))
return super(Reader, self).seek_realtime(realtime)
realtime = float(realtime.strftime("%s.%f")) * 1000000
return super(Reader, self).seek_realtime(int(realtime))
def seek_monotonic(self, monotonic, bootid=None):
"""Seek to a matching journal entry nearest to `monotonic` time.
@@ -229,6 +240,7 @@ class Reader(_Reader):
"""
if isinstance(monotonic, _datetime.timedelta):
monotonic = monotonic.totalseconds()
monotonic = int(monotonic * 1000000)
if isinstance(bootid, _uuid.UUID):
bootid = bootid.get_hex()
return super(Reader, self).seek_monotonic(monotonic, bootid)