2013-02-20 07:22:03 +04:00
/*-*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*-*/
2013-02-16 21:32:05 +04:00
/***
This file is part of systemd .
Copyright 2013 Steven Hiscocks , Zbigniew Jędrzejewski - Szmek
systemd is free software ; you can redistribute it and / or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation ; either version 2.1 of the License , or
( at your option ) any later version .
systemd is distributed in the hope that it will be useful , but
WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public License
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
2013-02-08 23:41:21 +04:00
# include <Python.h>
# include <structmember.h>
# include <datetime.h>
2013-02-22 16:33:06 +04:00
# include <stdio.h>
# include <systemd/sd-journal.h>
# include "pyutil.h"
# include "macro.h"
# include "util.h"
2013-02-08 23:41:21 +04:00
typedef struct {
PyObject_HEAD
sd_journal * j ;
2013-03-01 04:32:31 +04:00
} Reader ;
static PyTypeObject ReaderType ;
2013-02-08 23:41:21 +04:00
2013-02-17 20:26:10 +04:00
static int set_error ( int r , const char * path , const char * invalid_message ) {
if ( r > = 0 )
return r ;
if ( r = = - EINVAL & & invalid_message )
PyErr_SetString ( PyExc_ValueError , invalid_message ) ;
else if ( r = = - ENOMEM )
PyErr_SetString ( PyExc_MemoryError , " Not enough memory " ) ;
else {
errno = - r ;
PyErr_SetFromErrnoWithFilename ( PyExc_OSError , path ) ;
}
2013-03-07 20:28:44 +04:00
return - 1 ;
2013-02-17 20:26:10 +04:00
}
2013-03-16 02:10:51 +04:00
PyDoc_STRVAR ( module__doc__ ,
" Class to reads the systemd journal similar to journalctl. " ) ;
2013-02-23 04:11:36 +04:00
# 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 " } ,
2013-03-25 03:59:00 +04:00
{ } /* Sentinel */
2013-02-23 04:11:36 +04:00
} ;
static PyStructSequence_Desc Monotonic_desc = {
( char * ) " journal.Monotonic " ,
MonotonicType__doc__ ,
MonotonicType_fields ,
2 ,
} ;
# endif
2013-03-16 02:10:51 +04:00
2013-03-01 04:32:31 +04:00
static void Reader_dealloc ( Reader * self )
2013-02-08 23:41:21 +04:00
{
sd_journal_close ( self - > j ) ;
Py_TYPE ( self ) - > tp_free ( ( PyObject * ) self ) ;
}
2013-03-01 04:32:31 +04:00
PyDoc_STRVAR ( Reader__doc__ ,
2013-03-21 03:12:27 +04:00
" _Reader([flags | path]) -> ... \n \n "
" _Reader allows filtering and retrieval of Journal entries. \n "
2013-03-07 20:28:44 +04:00
" Note: this is a low-level interface, and probably not what you \n "
" want, use systemd.journal.Reader instead. \n \n "
2013-02-20 07:22:03 +04:00
" Argument `flags` sets open flags of the journal, which can be one \n "
" of, or ORed combination of constants: LOCAL_ONLY (default) opens \n "
" journal on local machine only; RUNTIME_ONLY opens only \n "
" volatile journal files; and SYSTEM_ONLY opens only \n "
2013-03-07 20:28:44 +04:00
" journal files of system services and the kernel. \n \n "
2013-02-20 07:22:03 +04:00
" Argument `path` is the directory of journal files. Note that \n "
2013-03-21 03:12:27 +04:00
" `flags` and `path` are exclusive. \n \n "
" _Reader implements the context manager protocol: the journal \n "
" will be closed when exiting the block. " ) ;
2013-03-01 04:32:31 +04:00
static int Reader_init ( Reader * self , PyObject * args , PyObject * keywds )
2013-02-08 23:41:21 +04:00
{
2013-03-07 20:28:44 +04:00
int flags = 0 , r ;
2013-02-20 06:58:54 +04:00
char * path = NULL ;
2013-02-08 23:41:21 +04:00
2013-02-20 06:58:54 +04:00
static const char * const kwlist [ ] = { " flags " , " path " , NULL } ;
if ( ! PyArg_ParseTupleAndKeywords ( args , keywds , " |iz " , ( char * * ) kwlist ,
& flags , & path ) )
2013-03-07 20:28:44 +04:00
return - 1 ;
if ( ! flags )
flags = SD_JOURNAL_LOCAL_ONLY ;
else
if ( path ) {
PyErr_SetString ( PyExc_ValueError , " cannot use both flags and path " ) ;
return - 1 ;
}
2013-02-08 23:41:21 +04:00
2013-02-16 21:29:57 +04:00
Py_BEGIN_ALLOW_THREADS
2013-02-20 07:11:02 +04:00
if ( path )
2013-02-08 23:41:21 +04:00
r = sd_journal_open_directory ( & self - > j , path , 0 ) ;
2013-02-20 07:11:02 +04:00
else
2013-02-08 23:41:21 +04:00
r = sd_journal_open ( & self - > j , flags ) ;
2013-02-16 21:29:57 +04:00
Py_END_ALLOW_THREADS
2013-02-08 23:41:21 +04:00
2013-02-17 20:26:10 +04:00
return set_error ( r , path , " Invalid flags or path " ) ;
2013-02-08 23:41:21 +04:00
}
2013-03-16 02:10:51 +04:00
2013-03-07 09:35:28 +04:00
PyDoc_STRVAR ( Reader_fileno__doc__ ,
" fileno() -> int \n \n "
" Get a file descriptor to poll for changes in the journal. \n "
" This method invokes sd_journal_get_fd(). \n "
" See man:sd_journal_get_fd(3). " ) ;
static PyObject * Reader_fileno ( Reader * self , PyObject * args )
{
2013-03-21 02:30:10 +04:00
int fd ;
fd = sd_journal_get_fd ( self - > j ) ;
set_error ( fd , NULL , NULL ) ;
if ( fd < 0 )
2013-03-07 09:35:28 +04:00
return NULL ;
2013-03-21 02:30:10 +04:00
return long_FromLong ( fd ) ;
2013-03-07 09:35:28 +04:00
}
2013-03-16 02:10:51 +04:00
2013-03-07 09:35:28 +04:00
PyDoc_STRVAR ( Reader_reliable_fd__doc__ ,
" reliable_fd() -> bool \n \n "
" Returns True iff the journal can be polled reliably. \n "
" This method invokes sd_journal_reliable_fd(). \n "
" See man:sd_journal_reliable_fd(3). " ) ;
static PyObject * Reader_reliable_fd ( Reader * self , PyObject * args )
{
int r ;
r = sd_journal_reliable_fd ( self - > j ) ;
set_error ( r , NULL , NULL ) ;
if ( r < 0 )
return NULL ;
return PyBool_FromLong ( r ) ;
}
2013-03-16 02:10:51 +04:00
2013-03-07 09:35:28 +04:00
PyDoc_STRVAR ( Reader_close__doc__ ,
2013-03-08 00:27:30 +04:00
" close() -> None \n \n "
2013-03-07 09:35:28 +04:00
" Free resources allocated by this Reader object. \n "
" This method invokes sd_journal_close(). \n "
" See man:sd_journal_close(3). " ) ;
static PyObject * Reader_close ( Reader * self , PyObject * args )
{
2013-03-18 09:12:25 +04:00
assert ( self ) ;
assert ( ! args ) ;
sd_journal_close ( self - > j ) ;
self - > j = NULL ;
Py_RETURN_NONE ;
}
2013-03-16 02:10:51 +04:00
2013-03-21 02:30:10 +04:00
PyDoc_STRVAR ( Reader_get_usage__doc__ ,
" get_usage() -> int \n \n "
2013-04-15 02:37:38 +04:00
" Returns the total disk space currently used by journal \n "
" files (in bytes). If `SD_JOURNAL_LOCAL_ONLY` was \n "
" passed when opening the journal this value will only reflect \n "
" the size of journal files of the local host, otherwise \n "
2013-03-21 02:30:10 +04:00
" of all hosts. \n \n "
" This method invokes sd_journal_get_usage(). \n "
" See man:sd_journal_get_usage(3). " ) ;
static PyObject * Reader_get_usage ( Reader * self , PyObject * args )
{
int r ;
uint64_t bytes ;
r = sd_journal_get_usage ( self - > j , & bytes ) ;
if ( set_error ( r , NULL , NULL ) )
return NULL ;
assert_cc ( sizeof ( unsigned long long ) = = sizeof ( bytes ) ) ;
return PyLong_FromUnsignedLongLong ( bytes ) ;
}
2013-03-18 09:12:25 +04:00
PyDoc_STRVAR ( Reader___enter____doc__ ,
" __enter__() -> self \n \n "
" Part of the context manager protocol. \n "
" Returns self. \n " ) ;
static PyObject * Reader___enter__ ( PyObject * self , PyObject * args )
{
assert ( self ) ;
assert ( ! args ) ;
Py_INCREF ( self ) ;
return self ;
}
PyDoc_STRVAR ( Reader___exit____doc__ ,
" __exit__(type, value, traceback) -> None \n \n "
" Part of the context manager protocol. \n "
" Closes the journal. \n " ) ;
static PyObject * Reader___exit__ ( Reader * self , PyObject * args )
{
assert ( self ) ;
2013-03-07 09:35:28 +04:00
sd_journal_close ( self - > j ) ;
2013-03-08 00:32:33 +04:00
self - > j = NULL ;
2013-03-07 09:35:28 +04:00
Py_RETURN_NONE ;
}
2013-03-16 02:10:51 +04:00
2013-03-21 03:12:27 +04:00
PyDoc_STRVAR ( Reader_next__doc__ ,
" next([skip]) -> bool \n \n "
" Go to the next log entry. Optional skip value means to go to \n "
" the `skip` \\ -th log entry. \n "
" Returns False if at end of file, True otherwise. " ) ;
static PyObject * Reader_next ( Reader * self , PyObject * args )
2013-02-08 23:41:21 +04:00
{
2013-02-22 16:33:06 +04:00
int64_t skip = 1LL ;
int r ;
2013-02-20 07:11:02 +04:00
2013-03-21 03:12:27 +04:00
if ( ! PyArg_ParseTuple ( args , " |L:next " , & skip ) )
2013-02-08 23:41:21 +04:00
return NULL ;
2013-02-16 21:29:57 +04:00
if ( skip = = 0LL ) {
2013-02-20 07:11:02 +04:00
PyErr_SetString ( PyExc_ValueError , " skip must be nonzero " ) ;
2013-02-16 21:29:57 +04:00
return NULL ;
}
Py_BEGIN_ALLOW_THREADS
2013-02-20 07:11:02 +04:00
if ( skip = = 1LL )
2013-02-08 23:41:21 +04:00
r = sd_journal_next ( self - > j ) ;
2013-02-20 07:11:02 +04:00
else if ( skip = = - 1LL )
2013-02-08 23:41:21 +04:00
r = sd_journal_previous ( self - > j ) ;
2013-02-20 07:11:02 +04:00
else if ( skip > 1LL )
2013-02-08 23:41:21 +04:00
r = sd_journal_next_skip ( self - > j , skip ) ;
2013-02-20 07:11:02 +04:00
else if ( skip < - 1LL )
2013-02-08 23:41:21 +04:00
r = sd_journal_previous_skip ( self - > j , - skip ) ;
2013-02-22 16:33:06 +04:00
else
assert_not_reached ( " should not be here " ) ;
2013-02-16 21:29:57 +04:00
Py_END_ALLOW_THREADS
2013-02-08 23:41:21 +04:00
2013-02-17 20:26:10 +04:00
set_error ( r , NULL , NULL ) ;
if ( r < 0 )
2013-02-08 23:41:21 +04:00
return NULL ;
2013-03-21 03:12:27 +04:00
return PyBool_FromLong ( r ) ;
}
2013-03-21 07:01:32 +04:00
static int extract ( const char * msg , size_t msg_len ,
PyObject * * key , PyObject * * value ) {
PyObject * k = NULL , * v ;
const char * delim_ptr ;
delim_ptr = memchr ( msg , ' = ' , msg_len ) ;
if ( ! delim_ptr ) {
PyErr_SetString ( PyExc_OSError ,
" journal gave us a field without '=' " ) ;
return - 1 ;
}
if ( key ) {
k = unicode_FromStringAndSize ( msg , delim_ptr - ( const char * ) msg ) ;
if ( ! k )
return - 1 ;
}
if ( value ) {
v = PyBytes_FromStringAndSize ( delim_ptr + 1 ,
( const char * ) msg + msg_len - ( delim_ptr + 1 ) ) ;
if ( ! v ) {
Py_XDECREF ( k ) ;
return - 1 ;
}
* value = v ;
}
if ( key )
* key = k ;
return 0 ;
}
PyDoc_STRVAR ( Reader_get__doc__ ,
" get(str) -> str \n \n "
" Return data associated with this key in current log entry. \n "
" Throws KeyError is the data is not available. " ) ;
static PyObject * Reader_get ( Reader * self , PyObject * args )
{
const char * field ;
const void * msg ;
size_t msg_len ;
PyObject * value ;
int r ;
assert ( self ) ;
assert ( args ) ;
if ( ! PyArg_ParseTuple ( args , " s:get " , & field ) )
return NULL ;
r = sd_journal_get_data ( self - > j , field , & msg , & msg_len ) ;
if ( r = = - ENOENT ) {
PyErr_SetString ( PyExc_KeyError , field ) ;
return NULL ;
} else if ( set_error ( r , NULL , " field name is not valid " ) )
return NULL ;
r = extract ( msg , msg_len , NULL , & value ) ;
if ( r < 0 )
return NULL ;
return value ;
}
2013-03-21 03:12:27 +04:00
PyDoc_STRVAR ( Reader_get_next__doc__ ,
" get_next([skip]) -> dict \n \n "
" Return dictionary of the next log entry. Optional skip value will \n "
" return the `skip` \\ -th log entry. Returns an empty dict on EOF. " ) ;
static PyObject * Reader_get_next ( Reader * self , PyObject * args )
{
PyObject _cleanup_Py_DECREF_ * tmp = NULL ;
PyObject * dict ;
const void * msg ;
size_t msg_len ;
int r ;
tmp = Reader_next ( self , args ) ;
if ( ! tmp )
return NULL ;
if ( tmp = = Py_False ) /* EOF */
2013-02-08 23:41:21 +04:00
return PyDict_New ( ) ;
dict = PyDict_New ( ) ;
2013-02-22 16:33:06 +04:00
if ( ! dict )
return NULL ;
2013-02-08 23:41:21 +04:00
SD_JOURNAL_FOREACH_DATA ( self - > j , msg , msg_len ) {
2013-02-22 16:33:06 +04:00
PyObject _cleanup_Py_DECREF_ * key = NULL , * value = NULL ;
2013-03-21 07:01:32 +04:00
r = extract ( msg , msg_len , & key , & value ) ;
if ( r < 0 )
2013-02-22 16:33:06 +04:00
goto error ;
2013-02-08 23:41:21 +04:00
if ( PyDict_Contains ( dict , key ) ) {
2013-02-22 16:33:06 +04:00
PyObject * cur_value = PyDict_GetItem ( dict , key ) ;
2013-02-15 20:59:50 +04:00
if ( PyList_CheckExact ( cur_value ) ) {
2013-02-22 16:33:06 +04:00
r = PyList_Append ( cur_value , value ) ;
if ( r < 0 )
goto error ;
} else {
PyObject _cleanup_Py_DECREF_ * tmp_list = PyList_New ( 0 ) ;
if ( ! tmp_list )
goto error ;
r = PyList_Append ( tmp_list , cur_value ) ;
if ( r < 0 )
goto error ;
r = PyList_Append ( tmp_list , value ) ;
if ( r < 0 )
goto error ;
2013-03-01 21:29:57 +04:00
r = PyDict_SetItem ( dict , key , tmp_list ) ;
2013-02-22 16:33:06 +04:00
if ( r < 0 )
goto error ;
2013-02-08 23:41:21 +04:00
}
2013-02-22 16:33:06 +04:00
} else {
r = PyDict_SetItem ( dict , key , value ) ;
if ( r < 0 )
goto error ;
2013-02-08 23:41:21 +04:00
}
}
2013-03-21 03:12:27 +04:00
return dict ;
2013-03-21 07:01:32 +04:00
2013-03-21 03:12:27 +04:00
error :
Py_DECREF ( dict ) ;
return NULL ;
}
2013-02-22 16:33:06 +04:00
2013-03-21 03:12:27 +04:00
PyDoc_STRVAR ( Reader_get_realtime__doc__ ,
" get_realtime() -> int \n \n "
" Return the realtime timestamp for the current journal entry \n "
" in microseconds. \n \n "
" Wraps sd_journal_get_realtime_usec(). \n "
" See man:sd_journal_get_realtime_usec(3). " ) ;
static PyObject * Reader_get_realtime ( Reader * self , PyObject * args )
{
uint64_t timestamp ;
int r ;
2013-02-22 16:33:06 +04:00
2013-03-21 03:12:27 +04:00
assert ( self ) ;
assert ( ! args ) ;
2013-02-22 16:33:06 +04:00
2013-03-21 03:12:27 +04:00
r = sd_journal_get_realtime_usec ( self - > j , & timestamp ) ;
if ( set_error ( r , NULL , NULL ) )
return NULL ;
2013-02-08 23:41:21 +04:00
2013-03-21 03:12:27 +04:00
assert_cc ( sizeof ( unsigned long long ) = = sizeof ( timestamp ) ) ;
return PyLong_FromUnsignedLongLong ( timestamp ) ;
}
2013-02-22 16:33:06 +04:00
2013-03-21 03:12:27 +04:00
PyDoc_STRVAR ( Reader_get_monotonic__doc__ ,
" get_monotonic() -> (timestamp, bootid) \n \n "
" Return the monotonic timestamp for the current journal entry \n "
" as a tuple of time in microseconds and bootid. \n \n "
" Wraps sd_journal_get_monotonic_usec(). \n "
" See man:sd_journal_get_monotonic_usec(3). " ) ;
static PyObject * Reader_get_monotonic ( Reader * self , PyObject * args )
{
uint64_t timestamp ;
sd_id128_t id ;
PyObject * monotonic , * bootid , * tuple ;
int r ;
assert ( self ) ;
assert ( ! args ) ;
r = sd_journal_get_monotonic_usec ( self - > j , & timestamp , & id ) ;
if ( set_error ( r , NULL , NULL ) )
return NULL ;
assert_cc ( sizeof ( unsigned long long ) = = sizeof ( timestamp ) ) ;
monotonic = PyLong_FromUnsignedLongLong ( timestamp ) ;
bootid = PyBytes_FromStringAndSize ( ( const char * ) & id . bytes , sizeof ( id . bytes ) ) ;
2013-02-23 04:11:36 +04:00
# if PY_MAJOR_VERSION >= 3
2013-03-21 03:12:27 +04:00
tuple = PyStructSequence_New ( & MonotonicType ) ;
2013-02-23 04:11:36 +04:00
# else
2013-03-21 03:12:27 +04:00
tuple = PyTuple_New ( 2 ) ;
2013-02-23 04:11:36 +04:00
# endif
2013-03-21 03:12:27 +04:00
if ( ! monotonic | | ! bootid | | ! tuple ) {
Py_XDECREF ( monotonic ) ;
Py_XDECREF ( bootid ) ;
Py_XDECREF ( tuple ) ;
return NULL ;
}
2013-02-23 04:11:36 +04:00
# if PY_MAJOR_VERSION >= 3
2013-03-21 03:12:27 +04:00
PyStructSequence_SET_ITEM ( tuple , 0 , monotonic ) ;
PyStructSequence_SET_ITEM ( tuple , 1 , bootid ) ;
2013-02-23 04:11:36 +04:00
# else
2013-03-21 03:12:27 +04:00
PyTuple_SET_ITEM ( tuple , 0 , monotonic ) ;
PyTuple_SET_ITEM ( tuple , 1 , bootid ) ;
2013-02-23 04:11:36 +04:00
# endif
2013-02-22 16:33:06 +04:00
2013-03-21 03:12:27 +04:00
return tuple ;
2013-02-08 23:41:21 +04:00
}
2013-03-16 02:10:51 +04:00
2013-03-01 04:32:31 +04:00
PyDoc_STRVAR ( Reader_get_previous__doc__ ,
2013-02-20 07:22:03 +04:00
" get_previous([skip]) -> dict \n \n "
" Return dictionary of the previous log entry. Optional skip value \n "
2013-02-20 08:03:32 +04:00
" will return the -`skip` \\ -th log entry. Equivalent to get_next(-skip). " ) ;
2013-03-01 04:32:31 +04:00
static PyObject * Reader_get_previous ( Reader * self , PyObject * args )
2013-02-08 23:41:21 +04:00
{
2013-02-20 07:22:03 +04:00
int64_t skip = 1LL ;
2013-03-21 03:12:27 +04:00
if ( ! PyArg_ParseTuple ( args , " |L:get_previous " , & skip ) )
2013-02-08 23:41:21 +04:00
return NULL ;
2013-02-20 06:58:54 +04:00
return PyObject_CallMethod ( ( PyObject * ) self , ( char * ) " get_next " ,
( char * ) " L " , - skip ) ;
2013-02-08 23:41:21 +04:00
}
2013-03-16 02:10:51 +04:00
2013-03-01 04:32:31 +04:00
PyDoc_STRVAR ( Reader_add_match__doc__ ,
2013-02-20 07:22:03 +04:00
" add_match(match) -> None \n \n "
" Add a match to filter journal log entries. All matches of different \n "
2013-02-20 08:03:32 +04:00
" fields are combined with logical AND, and matches of the same field \n "
" are automatically combined with logical OR. \n "
2013-02-20 07:22:03 +04:00
" Match is a string of the form \" FIELD=value \" . " ) ;
2013-03-01 04:32:31 +04:00
static PyObject * Reader_add_match ( Reader * self , PyObject * args , PyObject * keywds )
2013-02-08 23:41:21 +04:00
{
2013-02-16 22:53:52 +04:00
char * match ;
2013-02-20 07:11:02 +04:00
int match_len , r ;
2013-03-21 03:12:27 +04:00
if ( ! PyArg_ParseTuple ( args , " s#:add_match " , & match , & match_len ) )
2013-02-16 22:53:52 +04:00
return NULL ;
r = sd_journal_add_match ( self - > j , match , match_len ) ;
2013-02-17 20:26:10 +04:00
set_error ( r , NULL , " Invalid match " ) ;
if ( r < 0 )
return NULL ;
2013-02-08 23:41:21 +04:00
Py_RETURN_NONE ;
}
2013-03-16 02:10:51 +04:00
2013-03-01 04:32:31 +04:00
PyDoc_STRVAR ( Reader_add_disjunction__doc__ ,
2013-02-20 07:22:03 +04:00
" add_disjunction() -> None \n \n "
2013-02-20 08:03:32 +04:00
" Inserts a logical OR between matches added before and afterwards. " ) ;
2013-03-01 04:32:31 +04:00
static PyObject * Reader_add_disjunction ( Reader * self , PyObject * args )
2013-02-08 23:41:21 +04:00
{
int r ;
r = sd_journal_add_disjunction ( self - > j ) ;
2013-02-17 20:26:10 +04:00
set_error ( r , NULL , NULL ) ;
if ( r < 0 )
2013-02-08 23:41:21 +04:00
return NULL ;
Py_RETURN_NONE ;
}
2013-03-16 02:10:51 +04:00
2013-03-01 04:32:31 +04:00
PyDoc_STRVAR ( Reader_flush_matches__doc__ ,
2013-02-20 07:22:03 +04:00
" flush_matches() -> None \n \n "
2013-02-20 08:03:32 +04:00
" Clear all current match filters. " ) ;
2013-03-01 04:32:31 +04:00
static PyObject * Reader_flush_matches ( Reader * self , PyObject * args )
2013-02-08 23:41:21 +04:00
{
sd_journal_flush_matches ( self - > j ) ;
Py_RETURN_NONE ;
}
2013-03-16 02:10:51 +04:00
2013-03-07 09:26:24 +04:00
PyDoc_STRVAR ( Reader_seek_head__doc__ ,
" seek_head() -> None \n \n "
" Jump to the beginning of the journal. \n "
" This method invokes sd_journal_seek_head(). \n "
" See man:sd_journal_seek_head(3). " ) ;
static PyObject * Reader_seek_head ( Reader * self , PyObject * args )
2013-02-08 23:41:21 +04:00
{
2013-03-07 09:26:24 +04:00
int r ;
Py_BEGIN_ALLOW_THREADS
r = sd_journal_seek_head ( self - > j ) ;
Py_END_ALLOW_THREADS
if ( set_error ( r , NULL , NULL ) )
2013-02-08 23:41:21 +04:00
return NULL ;
2013-03-07 09:26:24 +04:00
Py_RETURN_NONE ;
}
2013-02-08 23:41:21 +04:00
2013-03-16 02:10:51 +04:00
2013-03-07 09:26:24 +04:00
PyDoc_STRVAR ( Reader_seek_tail__doc__ ,
" seek_tail() -> None \n \n "
2013-03-08 00:27:30 +04:00
" Jump to the end of the journal. \n "
2013-03-07 09:26:24 +04:00
" This method invokes sd_journal_seek_tail(). \n "
" See man:sd_journal_seek_tail(3). " ) ;
static PyObject * Reader_seek_tail ( Reader * self , PyObject * args )
{
int r ;
Py_BEGIN_ALLOW_THREADS
r = sd_journal_seek_tail ( self - > j ) ;
Py_END_ALLOW_THREADS
if ( set_error ( r , NULL , NULL ) )
2013-02-16 17:40:44 +04:00
return NULL ;
2013-02-08 23:41:21 +04:00
Py_RETURN_NONE ;
}
2013-03-16 02:10:51 +04:00
2013-03-01 04:32:31 +04:00
PyDoc_STRVAR ( Reader_seek_realtime__doc__ ,
2013-02-20 07:22:03 +04:00
" seek_realtime(realtime) -> None \n \n "
" Seek to nearest matching journal entry to `realtime`. Argument \n "
2013-03-21 02:40:05 +04:00
" `realtime` in specified in seconds. " ) ;
2013-03-01 04:32:31 +04:00
static PyObject * Reader_seek_realtime ( Reader * self , PyObject * args )
2013-02-08 23:41:21 +04:00
{
2013-02-20 07:11:02 +04:00
uint64_t timestamp ;
int r ;
2013-03-21 02:40:05 +04:00
if ( ! PyArg_ParseTuple ( args , " K:seek_realtime " , & timestamp ) )
2013-02-08 23:41:21 +04:00
return NULL ;
Py_BEGIN_ALLOW_THREADS
r = sd_journal_seek_realtime_usec ( self - > j , timestamp ) ;
Py_END_ALLOW_THREADS
2013-02-17 20:26:10 +04:00
if ( set_error ( r , NULL , NULL ) )
2013-02-08 23:41:21 +04:00
return NULL ;
Py_RETURN_NONE ;
}
2013-03-16 02:10:51 +04:00
2013-03-01 04:32:31 +04:00
PyDoc_STRVAR ( Reader_seek_monotonic__doc__ ,
2013-02-20 07:22:03 +04:00
" seek_monotonic(monotonic[, bootid]) -> None \n \n "
" Seek to nearest matching journal entry to `monotonic`. Argument \n "
2013-03-21 02:40:05 +04:00
" `monotonic` is an timestamp from boot in microseconds. \n "
2013-02-20 07:22:03 +04:00
" Argument `bootid` is a string representing which boot the \n "
" monotonic time is reference to. Defaults to current bootid. " ) ;
2013-03-01 04:32:31 +04:00
static PyObject * Reader_seek_monotonic ( Reader * self , PyObject * args )
2013-02-08 23:41:21 +04:00
{
2013-02-20 07:22:03 +04:00
char * bootid = NULL ;
2013-02-20 07:11:02 +04:00
uint64_t timestamp ;
2013-02-23 04:11:36 +04:00
sd_id128_t id ;
2013-02-20 07:11:02 +04:00
int r ;
2013-03-21 02:40:05 +04:00
if ( ! PyArg_ParseTuple ( args , " K|z:seek_monotonic " , & timestamp , & bootid ) )
2013-02-08 23:41:21 +04:00
return NULL ;
if ( bootid ) {
2013-02-23 04:11:36 +04:00
r = sd_id128_from_string ( bootid , & id ) ;
2013-02-17 20:26:10 +04:00
if ( set_error ( r , NULL , " Invalid bootid " ) )
2013-02-08 23:41:21 +04:00
return NULL ;
2013-02-17 20:26:10 +04:00
} else {
Py_BEGIN_ALLOW_THREADS
2013-02-23 04:11:36 +04:00
r = sd_id128_get_boot ( & id ) ;
2013-02-17 20:26:10 +04:00
Py_END_ALLOW_THREADS
if ( set_error ( r , NULL , NULL ) )
2013-02-08 23:41:21 +04:00
return NULL ;
}
Py_BEGIN_ALLOW_THREADS
2013-02-23 04:11:36 +04:00
r = sd_journal_seek_monotonic_usec ( self - > j , id , timestamp ) ;
2013-02-08 23:41:21 +04:00
Py_END_ALLOW_THREADS
2013-02-17 20:26:10 +04:00
if ( set_error ( r , NULL , NULL ) )
2013-02-08 23:41:21 +04:00
return NULL ;
2013-03-21 02:40:05 +04:00
2013-02-08 23:41:21 +04:00
Py_RETURN_NONE ;
}
2013-02-17 20:26:10 +04:00
2013-03-16 02:10:51 +04:00
2013-03-01 04:32:31 +04:00
PyDoc_STRVAR ( Reader_wait__doc__ ,
2013-02-20 08:03:32 +04:00
" wait([timeout]) -> state change (integer) \n \n "
" Wait for a change in the journal. Argument `timeout` specifies \n "
2013-03-21 02:40:05 +04:00
" 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 "
2013-02-20 07:22:03 +04:00
" Will return constants: NOP if no change; APPEND if new \n "
" entries have been added to the end of the journal; and \n "
2013-04-15 02:37:38 +04:00
" INVALIDATE if journal files have been added or removed. \n \n "
" See man:sd_journal_wait(3) for further discussion. " ) ;
2013-03-21 02:40:05 +04:00
static PyObject * Reader_wait ( Reader * self , PyObject * args )
2013-02-08 23:41:21 +04:00
{
2013-02-20 06:58:54 +04:00
int r ;
2013-03-21 02:40:05 +04:00
int64_t timeout ;
2013-02-20 06:58:54 +04:00
2013-03-21 02:40:05 +04:00
if ( ! PyArg_ParseTuple ( args , " |L:wait " , & timeout ) )
2013-02-08 23:41:21 +04:00
return NULL ;
2013-02-16 21:29:57 +04:00
Py_BEGIN_ALLOW_THREADS
2013-03-21 02:40:05 +04:00
r = sd_journal_wait ( self - > j , timeout ) ;
2013-02-16 21:29:57 +04:00
Py_END_ALLOW_THREADS
2013-03-06 08:23:09 +04:00
if ( set_error ( r , NULL , NULL ) < 0 )
2013-02-16 21:29:57 +04:00
return NULL ;
2013-02-17 20:26:10 +04:00
2013-02-17 06:54:09 +04:00
return long_FromLong ( r ) ;
2013-02-08 23:41:21 +04:00
}
2013-03-16 02:10:51 +04:00
2013-03-01 04:32:31 +04:00
PyDoc_STRVAR ( Reader_seek_cursor__doc__ ,
2013-02-20 07:22:03 +04:00
" seek_cursor(cursor) -> None \n \n "
2013-02-20 08:03:32 +04:00
" Seek to journal entry by given unique reference `cursor`. " ) ;
2013-03-01 04:32:31 +04:00
static PyObject * Reader_seek_cursor ( Reader * self , PyObject * args )
2013-02-08 23:41:21 +04:00
{
const char * cursor ;
2013-02-20 07:11:02 +04:00
int r ;
2013-03-21 03:12:27 +04:00
if ( ! PyArg_ParseTuple ( args , " s:seek_cursor " , & cursor ) )
2013-02-08 23:41:21 +04:00
return NULL ;
Py_BEGIN_ALLOW_THREADS
r = sd_journal_seek_cursor ( self - > j , cursor ) ;
Py_END_ALLOW_THREADS
2013-02-17 20:26:10 +04:00
if ( set_error ( r , NULL , " Invalid cursor " ) )
2013-02-08 23:41:21 +04:00
return NULL ;
Py_RETURN_NONE ;
}
2013-03-16 02:10:51 +04:00
2013-03-21 03:00:37 +04:00
PyDoc_STRVAR ( Reader_get_cursor__doc__ ,
" get_cursor() -> str \n \n "
" Return a cursor string for the current journal entry. \n \n "
" Wraps sd_journal_get_cursor(). See man:sd_journal_get_cursor(3). " ) ;
static PyObject * Reader_get_cursor ( Reader * self , PyObject * args )
{
char _cleanup_free_ * cursor = NULL ;
int r ;
assert ( self ) ;
assert ( ! args ) ;
r = sd_journal_get_cursor ( self - > j , & cursor ) ;
if ( set_error ( r , NULL , NULL ) )
return NULL ;
return unicode_FromString ( cursor ) ;
}
PyDoc_STRVAR ( Reader_test_cursor__doc__ ,
" test_cursor(str) -> bool \n \n "
" Test whether the cursor string matches current journal entry. \n \n "
" Wraps sd_journal_test_cursor(). See man:sd_journal_test_cursor(3). " ) ;
static PyObject * Reader_test_cursor ( Reader * self , PyObject * args )
{
const char * cursor ;
int r ;
assert ( self ) ;
assert ( args ) ;
2013-03-21 03:12:27 +04:00
if ( ! PyArg_ParseTuple ( args , " s:test_cursor " , & cursor ) )
2013-03-21 03:00:37 +04:00
return NULL ;
r = sd_journal_test_cursor ( self - > j , cursor ) ;
set_error ( r , NULL , NULL ) ;
if ( r < 0 )
return NULL ;
return PyBool_FromLong ( r ) ;
}
2013-03-01 04:32:31 +04:00
static PyObject * Reader_iter ( PyObject * self )
2013-02-08 23:41:21 +04:00
{
Py_INCREF ( self ) ;
return self ;
}
2013-03-01 04:32:31 +04:00
static PyObject * Reader_iternext ( PyObject * self )
2013-02-08 23:41:21 +04:00
{
2013-02-16 17:40:44 +04:00
PyObject * dict ;
2013-02-08 23:41:21 +04:00
Py_ssize_t dict_size ;
2013-02-20 06:58:54 +04:00
dict = PyObject_CallMethod ( self , ( char * ) " get_next " , ( char * ) " " ) ;
2013-02-17 18:27:59 +04:00
if ( PyErr_Occurred ( ) )
return NULL ;
2013-02-08 23:41:21 +04:00
dict_size = PyDict_Size ( dict ) ;
if ( ( int64_t ) dict_size > 0LL ) {
return dict ;
2013-02-22 16:33:06 +04:00
} else {
2013-02-08 23:41:21 +04:00
Py_DECREF ( dict ) ;
PyErr_SetNone ( PyExc_StopIteration ) ;
return NULL ;
}
}
2013-03-16 02:10:51 +04:00
2013-03-01 04:32:31 +04:00
PyDoc_STRVAR ( Reader_query_unique__doc__ ,
2013-02-20 07:22:03 +04:00
" query_unique(field) -> a set of values \n \n "
2013-02-20 08:03:32 +04:00
" Return a set of unique values appearing in journal for the \n "
" given `field`. Note this does not respect any journal matches. " ) ;
2013-03-01 04:32:31 +04:00
static PyObject * Reader_query_unique ( Reader * self , PyObject * args )
2013-02-08 23:41:21 +04:00
{
char * query ;
2013-02-20 07:11:02 +04:00
int r ;
const void * uniq ;
size_t uniq_len ;
PyObject * value_set , * key , * value ;
2013-03-21 03:12:27 +04:00
if ( ! PyArg_ParseTuple ( args , " s:query_unique " , & query ) )
2013-02-08 23:41:21 +04:00
return NULL ;
Py_BEGIN_ALLOW_THREADS
r = sd_journal_query_unique ( self - > j , query ) ;
Py_END_ALLOW_THREADS
2013-02-17 20:26:10 +04:00
if ( set_error ( r , NULL , " Invalid field name " ) )
2013-02-08 23:41:21 +04:00
return NULL ;
value_set = PySet_New ( 0 ) ;
2013-02-17 06:54:09 +04:00
key = unicode_FromString ( query ) ;
2013-02-08 23:41:21 +04:00
SD_JOURNAL_FOREACH_UNIQUE ( self - > j , uniq , uniq_len ) {
2013-02-20 07:11:02 +04:00
const char * delim_ptr ;
2013-02-08 23:41:21 +04:00
delim_ptr = memchr ( uniq , ' = ' , uniq_len ) ;
2013-02-22 16:33:06 +04:00
value = PyBytes_FromStringAndSize (
delim_ptr + 1 ,
( const char * ) uniq + uniq_len - ( delim_ptr + 1 ) ) ;
2013-02-08 23:41:21 +04:00
PySet_Add ( value_set , value ) ;
Py_DECREF ( value ) ;
}
Py_DECREF ( key ) ;
return value_set ;
}
2013-03-16 02:10:51 +04:00
PyDoc_STRVAR ( Reader_get_catalog__doc__ ,
" get_catalog() -> str \n \n "
" Retrieve a message catalog entry for the current journal entry. \n "
2013-03-21 07:01:32 +04:00
" Will throw IndexError if the entry has no MESSAGE_ID \n "
" and KeyError is the id is specified, but hasn't been found \n "
" in the catalog. \n \n "
2013-03-16 02:10:51 +04:00
" Wraps man:sd_journal_get_catalog(3). " ) ;
static PyObject * Reader_get_catalog ( Reader * self , PyObject * args )
{
int r ;
char _cleanup_free_ * msg = NULL ;
assert ( self ) ;
assert ( ! args ) ;
Py_BEGIN_ALLOW_THREADS
r = sd_journal_get_catalog ( self - > j , & msg ) ;
Py_END_ALLOW_THREADS
2013-03-21 07:01:32 +04:00
if ( r = = - ENOENT ) {
const void * mid ;
size_t mid_len ;
r = sd_journal_get_data ( self - > j , " MESSAGE_ID " , & mid , & mid_len ) ;
if ( r = = 0 ) {
const int l = sizeof ( " MESSAGE_ID " ) ;
assert ( mid_len > l ) ;
PyErr_Format ( PyExc_KeyError , " %.*s " , ( int ) mid_len - l ,
( const char * ) mid + l ) ;
} else if ( r = = - ENOENT )
PyErr_SetString ( PyExc_IndexError , " no MESSAGE_ID field " ) ;
else
set_error ( r , NULL , NULL ) ;
return NULL ;
} else if ( set_error ( r , NULL , NULL ) )
2013-03-16 02:10:51 +04:00
return NULL ;
return unicode_FromString ( msg ) ;
}
2013-03-16 02:10:51 +04:00
PyDoc_STRVAR ( get_catalog__doc__ ,
" get_catalog(id128) -> str \n \n "
" Retrieve a message catalog entry for the given id. \n "
" Wraps man:sd_journal_get_catalog_for_message_id(3). " ) ;
static PyObject * get_catalog ( PyObject * self , PyObject * args )
{
int r ;
char * id_ = NULL ;
sd_id128_t id ;
char _cleanup_free_ * msg = NULL ;
assert ( ! self ) ;
assert ( args ) ;
2013-03-16 02:10:51 +04:00
if ( ! PyArg_ParseTuple ( args , " z:get_catalog " , & id_ ) )
2013-03-16 02:10:51 +04:00
return NULL ;
r = sd_id128_from_string ( id_ , & id ) ;
if ( set_error ( r , NULL , " Invalid id128 " ) )
return NULL ;
Py_BEGIN_ALLOW_THREADS
r = sd_journal_get_catalog_for_message_id ( id , & msg ) ;
Py_END_ALLOW_THREADS
if ( set_error ( r , NULL , NULL ) )
return NULL ;
return unicode_FromString ( msg ) ;
}
2013-02-20 08:03:32 +04:00
PyDoc_STRVAR ( data_threshold__doc__ ,
2013-02-22 16:33:06 +04:00
" Threshold for field size truncation in bytes. \n \n "
2013-02-20 08:03:32 +04:00
" Fields longer than this will be truncated to the threshold size. \n "
" Defaults to 64Kb. " ) ;
2013-03-01 04:32:31 +04:00
static PyObject * Reader_get_data_threshold ( Reader * self , void * closure )
2013-02-08 23:41:21 +04:00
{
size_t cvalue ;
int r ;
r = sd_journal_get_data_threshold ( self - > j , & cvalue ) ;
2013-02-17 20:26:10 +04:00
if ( set_error ( r , NULL , NULL ) )
2013-02-08 23:41:21 +04:00
return NULL ;
2013-02-17 06:54:09 +04:00
return long_FromSize_t ( cvalue ) ;
2013-02-08 23:41:21 +04:00
}
2013-03-01 04:32:31 +04:00
static int Reader_set_data_threshold ( Reader * self , PyObject * value , void * closure )
2013-02-08 23:41:21 +04:00
{
2013-02-20 07:11:02 +04:00
int r ;
2013-02-08 23:41:21 +04:00
if ( value = = NULL ) {
2013-02-22 16:33:06 +04:00
PyErr_SetString ( PyExc_AttributeError , " Cannot delete data threshold " ) ;
2013-02-08 23:41:21 +04:00
return - 1 ;
}
2013-02-17 06:54:09 +04:00
if ( ! long_Check ( value ) ) {
2013-02-20 07:11:02 +04:00
PyErr_SetString ( PyExc_TypeError , " Data threshold must be an int " ) ;
2013-02-08 23:41:21 +04:00
return - 1 ;
}
2013-02-17 06:54:09 +04:00
r = sd_journal_set_data_threshold ( self - > j , ( size_t ) long_AsLong ( value ) ) ;
2013-02-17 20:26:10 +04:00
return set_error ( r , NULL , NULL ) ;
2013-02-08 23:41:21 +04:00
}
2013-03-16 02:10:51 +04:00
2013-03-16 02:10:51 +04:00
PyDoc_STRVAR ( closed__doc__ ,
" True iff journal is closed " ) ;
static PyObject * Reader_get_closed ( Reader * self , void * closure )
{
return PyBool_FromLong ( self - > j = = NULL ) ;
}
2013-03-16 02:10:51 +04:00
2013-03-16 02:10:51 +04:00
static PyGetSetDef Reader_getsetters [ ] = {
2013-02-20 06:58:54 +04:00
{ ( char * ) " data_threshold " ,
2013-03-01 04:32:31 +04:00
( getter ) Reader_get_data_threshold ,
( setter ) Reader_set_data_threshold ,
2013-02-20 08:03:32 +04:00
( char * ) data_threshold__doc__ ,
2013-02-20 06:58:54 +04:00
NULL } ,
2013-03-16 02:10:51 +04:00
{ ( char * ) " closed " ,
( getter ) Reader_get_closed ,
NULL ,
( char * ) closed__doc__ ,
NULL } ,
2013-03-25 03:59:00 +04:00
{ } /* Sentinel */
2013-02-08 23:41:21 +04:00
} ;
2013-03-01 04:32:31 +04:00
static PyMethodDef Reader_methods [ ] = {
2013-03-07 09:35:28 +04:00
{ " fileno " , ( PyCFunction ) Reader_fileno , METH_NOARGS , Reader_fileno__doc__ } ,
{ " reliable_fd " , ( PyCFunction ) Reader_reliable_fd , METH_NOARGS , Reader_reliable_fd__doc__ } ,
{ " close " , ( PyCFunction ) Reader_close , METH_NOARGS , Reader_close__doc__ } ,
2013-03-21 02:30:10 +04:00
{ " get_usage " , ( PyCFunction ) Reader_get_usage , METH_NOARGS , Reader_get_usage__doc__ } ,
2013-03-18 09:12:25 +04:00
{ " __enter__ " , ( PyCFunction ) Reader___enter__ , METH_NOARGS , Reader___enter____doc__ } ,
{ " __exit__ " , ( PyCFunction ) Reader___exit__ , METH_VARARGS , Reader___exit____doc__ } ,
2013-03-21 03:12:27 +04:00
{ " next " , ( PyCFunction ) Reader_next , METH_VARARGS , Reader_next__doc__ } ,
2013-03-21 07:01:32 +04:00
{ " get " , ( PyCFunction ) Reader_get , METH_VARARGS , Reader_get__doc__ } ,
2013-03-01 04:32:31 +04:00
{ " get_next " , ( PyCFunction ) Reader_get_next , METH_VARARGS , Reader_get_next__doc__ } ,
{ " get_previous " , ( PyCFunction ) Reader_get_previous , METH_VARARGS , Reader_get_previous__doc__ } ,
2013-03-21 03:12:27 +04:00
{ " get_realtime " , ( PyCFunction ) Reader_get_realtime , METH_NOARGS , Reader_get_realtime__doc__ } ,
{ " get_monotonic " , ( PyCFunction ) Reader_get_monotonic , METH_NOARGS , Reader_get_monotonic__doc__ } ,
2013-03-01 04:32:31 +04:00
{ " add_match " , ( PyCFunction ) Reader_add_match , METH_VARARGS | METH_KEYWORDS , Reader_add_match__doc__ } ,
{ " add_disjunction " , ( PyCFunction ) Reader_add_disjunction , METH_NOARGS , Reader_add_disjunction__doc__ } ,
{ " flush_matches " , ( PyCFunction ) Reader_flush_matches , METH_NOARGS , Reader_flush_matches__doc__ } ,
2013-03-07 09:26:24 +04:00
{ " seek_head " , ( PyCFunction ) Reader_seek_head , METH_NOARGS , Reader_seek_head__doc__ } ,
{ " seek_tail " , ( PyCFunction ) Reader_seek_tail , METH_NOARGS , Reader_seek_tail__doc__ } ,
2013-03-01 04:32:31 +04:00
{ " seek_realtime " , ( PyCFunction ) Reader_seek_realtime , METH_VARARGS , Reader_seek_realtime__doc__ } ,
{ " seek_monotonic " , ( PyCFunction ) Reader_seek_monotonic , METH_VARARGS , Reader_seek_monotonic__doc__ } ,
{ " wait " , ( PyCFunction ) Reader_wait , METH_VARARGS , Reader_wait__doc__ } ,
{ " seek_cursor " , ( PyCFunction ) Reader_seek_cursor , METH_VARARGS , Reader_seek_cursor__doc__ } ,
2013-03-21 03:00:37 +04:00
{ " get_cursor " , ( PyCFunction ) Reader_get_cursor , METH_NOARGS , Reader_get_cursor__doc__ } ,
{ " test_cursor " , ( PyCFunction ) Reader_test_cursor , METH_VARARGS , Reader_test_cursor__doc__ } ,
2013-03-01 04:32:31 +04:00
{ " query_unique " , ( PyCFunction ) Reader_query_unique , METH_VARARGS , Reader_query_unique__doc__ } ,
2013-03-16 02:10:51 +04:00
{ " get_catalog " , ( PyCFunction ) Reader_get_catalog , METH_NOARGS , Reader_get_catalog__doc__ } ,
2013-03-25 03:59:00 +04:00
{ } /* Sentinel */
2013-02-08 23:41:21 +04:00
} ;
2013-03-01 04:32:31 +04:00
static PyTypeObject ReaderType = {
2013-02-08 23:41:21 +04:00
PyVarObject_HEAD_INIT ( NULL , 0 )
2013-03-01 04:32:31 +04:00
" _reader._Reader " , /*tp_name*/
sizeof ( Reader ) , /*tp_basicsize*/
2013-02-22 16:33:06 +04:00
0 , /*tp_itemsize*/
2013-03-01 04:32:31 +04:00
( destructor ) Reader_dealloc , /*tp_dealloc*/
2013-02-22 16:33:06 +04:00
0 , /*tp_print*/
0 , /*tp_getattr*/
0 , /*tp_setattr*/
0 , /*tp_compare*/
0 , /*tp_repr*/
0 , /*tp_as_number*/
0 , /*tp_as_sequence*/
0 , /*tp_as_mapping*/
0 , /*tp_hash */
0 , /*tp_call*/
0 , /*tp_str*/
0 , /*tp_getattro*/
0 , /*tp_setattro*/
0 , /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /*tp_flags*/
2013-03-01 04:32:31 +04:00
Reader__doc__ , /* tp_doc */
2013-02-22 16:33:06 +04:00
0 , /* tp_traverse */
0 , /* tp_clear */
0 , /* tp_richcompare */
0 , /* tp_weaklistoffset */
2013-03-01 04:32:31 +04:00
Reader_iter , /* tp_iter */
Reader_iternext , /* tp_iternext */
Reader_methods , /* tp_methods */
2013-02-22 16:33:06 +04:00
0 , /* tp_members */
2013-03-16 02:10:51 +04:00
Reader_getsetters , /* tp_getset */
2013-02-22 16:33:06 +04:00
0 , /* tp_base */
0 , /* tp_dict */
0 , /* tp_descr_get */
0 , /* tp_descr_set */
0 , /* tp_dictoffset */
2013-03-01 04:32:31 +04:00
( initproc ) Reader_init , /* tp_init */
2013-02-22 16:33:06 +04:00
0 , /* tp_alloc */
PyType_GenericNew , /* tp_new */
2013-02-08 23:41:21 +04:00
} ;
2013-03-16 02:10:51 +04:00
static PyMethodDef methods [ ] = {
2013-03-21 07:01:32 +04:00
{ " _get_catalog " , get_catalog , METH_VARARGS , get_catalog__doc__ } ,
2013-03-16 02:10:51 +04:00
{ NULL , NULL , 0 , NULL } /* Sentinel */
} ;
2013-02-20 08:03:32 +04:00
2013-02-08 23:41:21 +04:00
# if PY_MAJOR_VERSION >= 3
2013-03-16 02:10:51 +04:00
static PyModuleDef module = {
2013-02-08 23:41:21 +04:00
PyModuleDef_HEAD_INIT ,
" _reader " ,
2013-03-16 02:10:51 +04:00
module__doc__ ,
2013-02-08 23:41:21 +04:00
- 1 ,
2013-03-16 02:10:51 +04:00
methods ,
NULL , NULL , NULL , NULL
2013-02-08 23:41:21 +04:00
} ;
# endif
2013-02-23 04:11:36 +04:00
# if PY_MAJOR_VERSION >= 3
static bool initialized = false ;
# endif
2013-02-20 06:58:54 +04:00
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wmissing-prototypes"
2013-02-08 23:41:21 +04:00
PyMODINIT_FUNC
# if PY_MAJOR_VERSION >= 3
PyInit__reader ( void )
# else
2013-02-20 06:58:54 +04:00
init_reader ( void )
2013-02-08 23:41:21 +04:00
# endif
{
PyObject * m ;
PyDateTime_IMPORT ;
2013-03-01 04:32:31 +04:00
if ( PyType_Ready ( & ReaderType ) < 0 )
2013-02-08 23:41:21 +04:00
# if PY_MAJOR_VERSION >= 3
return NULL ;
# else
return ;
# endif
# if PY_MAJOR_VERSION >= 3
2013-03-16 02:10:51 +04:00
m = PyModule_Create ( & module ) ;
2013-02-08 23:41:21 +04:00
if ( m = = NULL )
return NULL ;
2013-02-23 04:11:36 +04:00
if ( ! initialized ) {
PyStructSequence_InitType ( & MonotonicType , & Monotonic_desc ) ;
initialized = true ;
}
2013-02-08 23:41:21 +04:00
# else
2013-03-16 02:10:51 +04:00
m = Py_InitModule3 ( " _reader " , methods , module__doc__ ) ;
2013-02-08 23:41:21 +04:00
if ( m = = NULL )
return ;
# endif
2013-03-01 04:32:31 +04:00
Py_INCREF ( & ReaderType ) ;
2013-02-23 04:11:36 +04:00
# if PY_MAJOR_VERSION >= 3
Py_INCREF ( & MonotonicType ) ;
# endif
2013-03-01 04:32:31 +04:00
if ( PyModule_AddObject ( m , " _Reader " , ( PyObject * ) & ReaderType ) | |
2013-02-23 04:11:36 +04:00
# if PY_MAJOR_VERSION >= 3
PyModule_AddObject ( m , " Monotonic " , ( PyObject * ) & MonotonicType ) | |
# endif
2013-02-22 16:33:06 +04:00
PyModule_AddIntConstant ( m , " NOP " , SD_JOURNAL_NOP ) | |
PyModule_AddIntConstant ( m , " APPEND " , SD_JOURNAL_APPEND ) | |
PyModule_AddIntConstant ( m , " INVALIDATE " , SD_JOURNAL_INVALIDATE ) | |
PyModule_AddIntConstant ( m , " LOCAL_ONLY " , SD_JOURNAL_LOCAL_ONLY ) | |
PyModule_AddIntConstant ( m , " RUNTIME_ONLY " , SD_JOURNAL_RUNTIME_ONLY ) | |
PyModule_AddIntConstant ( m , " SYSTEM_ONLY " , SD_JOURNAL_SYSTEM_ONLY ) ) {
# if PY_MAJOR_VERSION >= 3
Py_DECREF ( m ) ;
return NULL ;
# endif
}
2013-02-08 23:41:21 +04:00
# if PY_MAJOR_VERSION >= 3
return m ;
# endif
}
2013-02-20 06:58:54 +04:00
# pragma GCC diagnostic pop