Imported Upstream version 0.14.2

This commit is contained in:
Christoph Berg 2015-04-18 12:01:23 +02:00
parent 85f75e9d49
commit 8da8cdf17a
96 changed files with 7774 additions and 5015 deletions

View File

@ -1 +1 @@
0.11.1
0.14.2

View File

@ -1 +1 @@
0.11.1
0.14.2

623
ChangeLog
View File

@ -1,3 +1,626 @@
2012-09-10 The Quarterback Library Release Team <quarterback-devel@fedorahosted.org>
Fix "make distcheck"
Bump the version to 0.14.2
2012-09-07 Виноградов Василий <wmdlr@yandex.ru>
Get libqb building on cygwin.
2012-09-06 Angus Salkeld <asalkeld@redhat.com>
Merge pull request #42 from jsgf/master
Three fixes for ipc_us.c
2012-09-06 Jeremy Fitzhardinge <jeremy@exablox.com>
ipc_us: slightly more robust cmsg handling
Cope with multiple cmsg structures in the received msg.
ipc_us: on Linux, set SO_PASSCRED on the sending socket too
Linux doesn't pass credential information by default, only when it has
been specifically requested with SO_PASSCRED. This means there's a
race between when the ipc server side has set up and is listening on the
socket, and when the client may connect; if the client connects and sends
its first message before the server has set SO_PASSCRED on the socket,
then there will be no ucred information associated with the message.
The fix is to set SO_PASSCRED on the client socket as well, so that
the message will always have a ucred associated with it when the server
reads it.
Without this change, around 1% of cpg_model_initialize() calls fail
with CS_ERR_ACCESS.
(This Linux behaviour was introduced just on a year ago in
16e5726269611b71c930054ffe9b858c1cea88eb "af_unix: dont send
SCM_CREDENTIALS by default".)
ipc_us: clear request unused fields
Clear unused request fields and padding so that valgrind doesn't complain
about undefined data being sent over the socket.
2012-09-05 Andrew Beekhof <andrew@beekhof.net>
TEST: Include writing and reading the blackbox in the log_long_msg test
2012-09-05 Angus Salkeld <asalkeld@redhat.com>
LOG: fix qb_vsnprintf_deserialize()
the strlcat was not call correctly, it needs the
original string to find the end and return the
correct length.
2012-09-01 Angus Salkeld <asalkeld@redhat.com>
Merge pull request #41 from jsgf/master
Fix some 64-bit big-endian issues
2012-09-01 Jeremy Fitzhardinge <jeremy@goop.org>
blackbox: fix 64-bit big-endian issues
Two issues:
1. when writing out the function name length, don't just write the 4 MSB
of the size
2. when reading the time, don't just use the 4 MSB of the time as the
timestamp; the log contains a full time_t, so we may as well use it.
2012-08-31 Angus Salkeld <asalkeld@redhat.com>
Remove IPC_NEEDS_RESPONSE_ACK and turn off shm ipc on solaris
Define unix path max for openbsd
Only turn on ipc_needs_response_ack=yes for solaris
Hopefully I can kill this option.
Some improvements to kqueue usage.
2012-08-30 Angus Salkeld <asalkeld@redhat.com>
kqueue: drop log message to trace.
2012-08-29 Angus Salkeld <asalkeld@redhat.com>
Fix splint warning
openbsd requires netinet/in.h before arpa/inet.h
Avoid strcpy() use strlcpy() instead.
Fix kqueue complile warnings
openbsd doesn't have EBADMSG
openbsd has a different UNIX_PATH_MAX
103 other bsd's are 108
LOG: change qb_vsprintf_serialize() into qb_vsnprintf_serialize()
This is to prevent overwriting the ringbuffer.
Also remove stpcpy() as it is not used anymore.
TEST: increase timeout to 6 secs as the recv timeout is 5 secs
TEST: get the logic right - grrr.
Turn off attribute_section on netbsd
Some missing pshared semaphore checks
Cleanup the checks for pshared semaphores
Add a config check for pthread_mutexattr_setpshared
Not available on netbsd
2012-08-28 Angus Salkeld <asalkeld@redhat.com>
Remove uses of timersub and use qb_util_stopwatch
RB: change the #error to ENOTSUP if no usable shared process sem
This is mainly on mac.
LOOP-KQUEUE: fix reference before assignment.
2012-08-27 Fabio M. Di Nitto <fdinitto@redhat.com>
build: fix libqb.pc creation and make maintainer-clean
LIB_RT is unnecessary around. AC_CHECK_LIBS will do the right thing
similar for the other libs that are all exported via LIBS
2012-08-27 Angus Salkeld <asalkeld@redhat.com>
LOG: Make sure the semaphores are initialized.
2012-08-24 Fabio M. Di Nitto <fdinitto@redhat.com>
build: remove bashism in cc support check
this is required for all systems that don't use bash for /bin/sh
2012-08-24 Angus Salkeld <asalkeld@redhat.com>
Catch disconnected sockets on Solaris
It seems like poll() was not producing a POLLHUP
so we rely on qb_ipc_us_recv() returning -ENOTCONN.
Merge pull request #40 from jsgf/master
Merge Jeremy's clang bugfixes.
2012-08-24 Jeremy Fitzhardinge <jeremy@exablox.com>
Don't free rb->shared_hdr in qb_rb_create_from_file()
Since qb_rb_close() frees it by munmapping it.
Check error return of qb_ipcs_uc_recv_and_auth()
If it fails, then &ugp isn't initialized.
2012-08-23 Andrew Beekhof <andrew@beekhof.net>
Fix removal of automatically installed doc files when building rpms
2012-08-22 Angus Salkeld <asalkeld@redhat.com>
Add the mailing list to the travis email notifications.
Work around debian not setting the arch path in splint.
So just adding both i386 and x86_64 to the path.
Ref: http://lists.gnu.org/archive/html/gpsd-dev/2012-05/msg00221.html
Remove color-tests and parallel-tests automake options.
This is just too painful for buildsystems like koji and travis.
You can't get access to the detailed output (error logs) that
otherwise be printed to screen.
I can't find a way to disable them on the command line (that
would be the best solution).
Add travis continuous integration config
2012-07-20 Angus Salkeld <asalkeld@redhat.com>
Merge pull request #39 from davidvossel/log_tag_fix
LOG: Invoke custom log filter function if tag changes
2012-07-20 David Vossel <dvossel@redhat.com>
LOG: Invoke custom log filter function if tag changes
2012-07-19 Jim Meyering <jim@meyering.net>
tests/rbwriter: don't ignore write failure
Here's another fix.
In adjusting the printf, I added a cast and switched to %5ld.
I would have preferred to use %5jd as the printf format (i.e., then no
cast is needed), but saw no other uses of the "j" directive, so perhaps
you do not yet depend on printf with such support.
From 6d5d3af35d1f6851537f7af8996d1106c1ebe435 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering@redhat.com>
Date: Wed, 18 Jul 2012 17:54:38 +0200
Subject: [PATCH] tests/rbwriter: don't ignore write failure
Spotted by coverity:
This less-than-zero comparison of an unsigned value is never true.
"res < 0U".
http://libqb.org/html/0.14.1/coverity/1/7rbwriter.c.html#error
ipcs: avoid use-after-free for size-0 || disconnect-request
Hi,
Glancing through coverity-reported issues,
I saw that this one required attention:
From 70f1f689022321710405f16dc45b3df30c22bc59 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering@redhat.com>
Date: Wed, 18 Jul 2012 17:34:17 +0200
Subject: [PATCH] ipcs: avoid use-after-free for size-0 || disconnect-request
spotted by coverity:
http://libqb.org/html/0.14.1/coverity/1/265ipcs.c.html#error
2012-07-17 The Quarterback Library Release Team <quarterback-devel@fedorahosted.org>
Bump the version to 0.14.1
2012-07-17 Angus Salkeld <asalkeld@redhat.com>
RB: set the new read pointer after clearing the header.
This is to prevent a situation where a fast writer will
write their new chunk between setting the new read pointer
and clearing the header.
RB: improve the debug print outs
RB: be more explicit about the word alignment
RB: cleanup the macros for wrapping the index
RB: use sem_getvalue as a tie breaker when read_pt == write_pt
RB: if read or peek don't get the message then re-post to the semaphore
RB: convert the rb_peek() status into a recv like status.
peek returns 0 on no data, so convert that to -EAGAIN.
RB: use internal reclaim function
IPC: use calloc instead of malloc to fix valgrind warnings
This is to cleanup some valgrind warnings.
2012-07-14 Angus Salkeld <asalkeld@redhat.com>
Upgrade the doxygen config.
The new doxygen says SHOW_DIRECTORIES is deprecated.
Fix a valgrind error.
just use the receive buffer, as it will be big enough.
2012-06-22 The Quarterback Library Release Team <quarterback-devel@fedorahosted.org>
Bump the version to 0.14.0
2012-06-14 Angus Salkeld <asalkeld@redhat.com>
LOG: fix threaded logging.
This has been broken for a year - yikes!
Thanks to Voznesensky Vladimir for spotting it.
2012-06-13 Angus Salkeld <asalkeld@redhat.com>
Add user control of the permissions that are set on the shared mem files
2012-06-07 Andrew Beekhof <andrew@beekhof.net>
LOG: Restrict string trucation during serialization to when a precision is specified
LOG: Gracefully fail when the caller exceeds QB_LOG_MAX_LEN
LOG: Observe field widths when serializing string arguments
2012-06-07 Angus Salkeld <asalkeld@redhat.com>
RB: use the same mechanism in reclaim as read/peek to detect end-of-ring
2012-06-06 Angus Salkeld <asalkeld@redhat.com>
Add needs_response_ack option to ./check
RB: fix wrong sem_flg IPC_NOWAIT option
The #ifdef was the wrong way around causing
the sem to return early with EAGAIN.
TESTS: fix warning about unused functions
Remove D_FORTIFY_SOURCE from check.
Can't seem to get this to work on F17.
Open shared mem file in /dev/shm only for linux
Don't use msg_flags on solaris (recvmsg).
Turn off attribute_section on solaris
ipc example: add -e (events) option
use events instead of responses
IPC: if the server returns EAGAIN or ETIMEOUT the check the connection
Mainly useful for shm, as the ringbuffer doesn't know the state
of the connection.
2012-06-05 Angus Salkeld <asalkeld@redhat.com>
LOG: make it possible to fsync() on each file log.
2012-06-04 Angus Salkeld <asalkeld@redhat.com>
IPC: make sure that the created callback happens before dispatches
This only happened on the socket ipc type.
LOG: fix the printing of %p in the blackbox
2012-06-01 Angus Salkeld <asalkeld@redhat.com>
IPC: On bsd's use the notifier for responses
The point of this is to catch connection failures
more reliably.
IPC: interpret ECONNRESET and EPIPE as ENOTCONN
2012-05-31 Angus Salkeld <asalkeld@redhat.com>
cleanup some warnings
config: use newer AC_COMPILE_IFELSE()
2012-05-28 Angus Salkeld <asalkeld@redhat.com>
blackbox: fix %p formatting
LOG: put all fields in the blackbox (added priority and tags)
Fixes #36
example: make the priority uint8_t
Remove strerror out of check_funcs
We only use strerror_r
RB: fix compiler warning.
Add replacement function stpcpy
Add missing AC_TYPE_UINT16_T to configure.ac
Use AC_FUNC_STRERROR_R and STRERROR_R_CHAR_P
Add stpcpy strcasecmp to the check_funcs
Move some conditional defines into code (from the configure script)
Remove some unused configure checks
Remove message queues
Check for union semun properly
Blackbox: provide more space for log messages when reading from the blackbox.
This is to allow for the header (16bytes and variable length function).
so if someone has a function name > 400 chars it will break. I
recon that will do:)
2012-05-28 Andrew Beekhof <andrew@beekhof.net>
Add the blackbox reader manpage to the spec file
Enable error logging for the blackbox reader
RB: Read the file size into an initialized variable of the correct size
2012-05-28 Angus Salkeld <asalkeld@redhat.com>
Add a tool to dump the blackbox.
2012-05-25 Angus Salkeld <asalkeld@redhat.com>
RB: to be safer save the read and write pointers at the top of the blackbox
2012-05-24 Jim Meyering <jim@meyering.net>
avoid unwarranted use of strncpy: use memcpy instead
* lib/log_format.c (qb_vsnprintf_deserialize): We know that there are
len or more non-NUL bytes in the source string, so it's clearer to
use memcpy.
2012-05-24 Angus Salkeld <asalkeld@redhat.com>
blackbox: fix the print_from_file()
RB: add an option to not use any semaphores
(brought over from the "speed" branch)
LOG: tweak the blackbox format string
LOG: accept NULL strings into the blackbox
LOG: protect close and reload from calling log
Logging during these operations is temporarly disabled.
2012-05-21 Angus Salkeld <asalkeld@redhat.com>
Add benchmark option (-b) to examples/ipcclient
TEST: make rbreader/writer more like the other benchmarking apps
2012-05-16 Angus Salkeld <asalkeld@redhat.com>
IPC: log the connection description in all logs
TEST: re-organise the ipc test suites
IPC: only modify the dispatch if we get EAGAIN
2012-05-12 Jan Friesse <jfriesse@redhat.com>
Correctly display timestamp in blackbox
On little endian architectures where time_t is 64-bit long integer could
happen, that instead of displaying correct timestamp, random data was
used, because of memcpy.
Solution is to memcpy to real 32-bit variable and then assing this value
to timestamp. This will let compiler decide endianity and store number
correctly.
2012-05-10 Angus Salkeld <asalkeld@redhat.com>
Add a more verbose version of the library versioning text.
Bump the library version to 0.13.0
Remove unneccessary __attribute__ ((aligned(8))) from internal headers
IPC: add a new function to get (and alloc) the extended stats.
This should handle any further additions to the stats
as the library allocs the struct.
Revert "Add the event queue length to the connection stats."
This reverts commit 6b7da3f5315473c05b5939903d97be2e8ade4c8c.
IPC: cleanup better on a failed client connect.
IPC(soc): be more consistent with control struct size
IPC: kill a compiler warning
IPC(soc): pass in the correct size into munmap()
2012-05-10 The Quarterback Library Release Team <quarterback-devel@fedorahosted.org>
Bump the lib version to 0.12.0
2012-05-10 Angus Salkeld <asalkeld@redhat.com>
TEST: Use /bin/sh not /bin/bash
TEST: check for lost shared mem on bsd too
rb: cleanup the semaphores
- the way they are selected
- rpl_sem.c the error handling
Fix some small issues in ./check
2012-05-09 Angus Salkeld <asalkeld@redhat.com>
Cleanup the .gitignore files
configure.ac tweaks
Thanks again to Igor Pashev.
Remove HZ and use sysconf instead.
SUN_LEN() macro is present if __EXTENSIONS__ is defined on Illumos
A bit reworked but originally from Igor Pashev:
https://github.com/ip1981/libqb/commit/84c47f8160a9a78f068cc5b0d40b3901c065cfa2
Note: __EXTENSIONS__ also defines _GNU_SOURCE, so removing it as well.
2012-05-09 Igor Pashev <pashev.igor@gmail.com>
PF_UNIX is a POSIX standard name
Test for log facility names
2012-05-09 Angus Salkeld <asalkeld@redhat.com>
IPC: drop log message to debug.
this can be noisy when there are a lot of transient
connections.
2012-05-03 Angus Salkeld <asalkeld@redhat.com>
IPC: fix retrying of partial recv's and sends.
Move to send() instead of sendmsg() as it's easier
to track resending partial messages.
IPC: initialize enough shared mem for all 3 one way connections.
2012-05-02 Angus Salkeld <asalkeld@redhat.com>
IPC: keep retrying to recv the socket message if partially recv'ed (part 2)
IPC: keep retrying to recv the socket message if partially recv'ed
IPC: handle the server shutdown better
IPC: handle a connection disconnect from the server better
Only problem with SOCKET.
2012-05-01 Angus Salkeld <asalkeld@redhat.com>
IPC: make it possible to send events in the connected callback.
This was only a problem with QB_IPC_SOCKET.
Add the event queue length to the connection stats.
IPC: add a is_connected client side function.
Fix typo in ./check
docs: clarify the need to use request/response headers
Remove unused local variable
2012-04-30 Angus Salkeld <asalkeld@redhat.com>
IPC: change the socket recv function to read the response header.
It needs to only recv the size of this message, else we recv more
than one message and effectively drop messages (hidden at the end
of the current message).
Add some special commands into the ipc example
type "events" and the server will send 10 events.
type 'kill' into the client and this will simulate the server dying.
TEST: improve the tracing in the ipc tests.
2012-04-30 Andrew Beekhof <andrew@beekhof.net>
Make "make (s)rpm" work more reliably
Make sure the version number is re-calculated on each run.
2012-04-30 Angus Salkeld <asalkeld@redhat.com>
TEST: add a test to confirm we get the events we send.
TEST: reuse send_and_check for events.
IPC: make it possible for a root client to talk to a non-root server.
2012-04-26 Angus Salkeld <asalkeld@redhat.com>
Run ./Lindent in the examples directory
Add some debug code to the ipcclient example
IPC: make sure ipc (socket) clients can connect to a server running as root.
2012-04-23 Angus Salkeld <asalkeld@redhat.com>
IPC: allow qb to bump the max_message_size
I think this is more user friendly.
IPC: check for a sane minimum max_message_size
add rpl_sem.h loop_poll_int.h to noinst_headers
2012-04-04 Angus Salkeld <asalkeld@redhat.com>
Handle errors more consistently
call recv_ready on socket types
Handle a recv of size 0
make bsd shm path better by default.
Fix kqueue on freebsd.
Get the example socket includes right.
Fix kqueue compiling.
POLL: seperate out the poll/epoll and add kqueue
2012-04-03 Jan Friesse <jfriesse@redhat.com>
Test existence of getpeer* functions
Add inet header to tcpclient example
Don't link with setpshared if unavailable
NetBSD doesn't have semun defined
2012-03-28 Jan Friesse <jfriesse@redhat.com>
Use MADV_NOSYNC only on systems where available
Use SCHED_BATCH only on platforms where available
2012-03-27 Angus Salkeld <asalkeld@redhat.com>
Fix a bug introduced by the bsd patch.
I missed the non-native case.
Cleanup the selection of semaphores to use
Fix some leaks in the logging.
Mainly for valgrind purposes.
2012-03-24 Angus Salkeld <asalkeld@redhat.com>
Try and improve the portability on bsd variants.
Also add a QB_IPC_NATIVE type that selects the best ipc type available.
2012-03-11 The Quarterback Library Release Team <quarterback-devel@fedorahosted.org>
Bump the version to 0.11.1

View File

@ -41,7 +41,7 @@ ACLOCAL_AMFLAGS = -I m4
dist_doc_DATA = COPYING INSTALL README.markdown
SUBDIRS = include lib docs tests examples
SUBDIRS = include lib docs tools tests examples
doxygen:
$(MAKE) -C docs doxygen
@ -107,12 +107,16 @@ RPMBUILDOPTS = --define "_sourcedir $(abs_builddir)" \
--define "_srcrpmdir $(abs_builddir)" \
--define "_rpmdir $(abs_builddir)"
tarball: $(TARFILE)
srpm: clean
$(MAKE) $(SPEC) $(TARFILE)
autoreconf -if
$(MAKE) $(SPEC) tarball
rpmbuild $(RPMBUILDOPTS) --nodeps -bs $(SPEC)
rpm: clean
$(MAKE) $(SPEC) $(TARFILE)
autoreconf -if
$(MAKE) $(SPEC) tarball
rpmbuild $(RPMBUILDOPTS) -ba $(SPEC)
# release/versioning

View File

@ -58,8 +58,9 @@ host_triplet = @host@
subdir = .
DIST_COMMON = $(am__configure_deps) $(dist_doc_DATA) \
$(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(top_srcdir)/configure COPYING INSTALL compile config.guess \
config.sub depcomp install-sh ltmain.sh missing
$(top_srcdir)/configure COPYING INSTALL build-aux/compile \
build-aux/config.guess build-aux/config.sub build-aux/depcomp \
build-aux/install-sh build-aux/ltmain.sh build-aux/missing
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
@ -212,7 +213,6 @@ LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIB_RT = @LIB_RT@
LINT_FLAGS = @LINT_FLAGS@
LIPO = @LIPO@
LN_S = @LN_S@
@ -315,7 +315,7 @@ MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure depcomp \
ACLOCAL_AMFLAGS = -I m4
dist_doc_DATA = COPYING INSTALL README.markdown
SUBDIRS = include lib docs tests examples
SUBDIRS = include lib docs tools tests examples
RPMBUILDOPTS = --define "_sourcedir $(abs_builddir)" \
--define "_specdir $(abs_builddir)" \
--define "_builddir $(abs_builddir)" \
@ -910,12 +910,16 @@ $(SPEC): $(SPEC).in
$(TARFILE):
$(MAKE) dist
tarball: $(TARFILE)
srpm: clean
$(MAKE) $(SPEC) $(TARFILE)
autoreconf -if
$(MAKE) $(SPEC) tarball
rpmbuild $(RPMBUILDOPTS) --nodeps -bs $(SPEC)
rpm: clean
$(MAKE) $(SPEC) $(TARFILE)
autoreconf -if
$(MAKE) $(SPEC) tarball
rpmbuild $(RPMBUILDOPTS) -ba $(SPEC)
.version:
echo $(VERSION) > $@-t && mv $@-t $@

View File

3934
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -6,11 +6,14 @@ AC_PREREQ([2.61])
AC_INIT([libqb],
m4_esyscmd([build-aux/git-version-gen .tarball-version]),
[quarterback-devel@fedorahosted.org])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_SRCDIR([lib/ringbuffer.c])
AC_CONFIG_HEADERS([include/config.h include/qb/qbconfig.h])
AM_INIT_AUTOMAKE([-Wno-portability dist-xz color-tests parallel-tests])
AC_USE_SYSTEM_EXTENSIONS
AM_INIT_AUTOMAKE([-Wno-portability dist-xz])
dnl automake >= 1.11 offers --enable-silent-rules for suppressing the output from
dnl normal compilation. When a failure occurs, it will then display the full
dnl normal compilation. When a failure occurs, it will then display the full
dnl command line
dnl Wrap in m4_ifdef to avoid breaking on older platforms
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
@ -18,6 +21,7 @@ LT_PREREQ([2.2.6])
LT_INIT
AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_HOST
AC_PROG_LIBTOOL
AC_LANG([C])
@ -73,11 +77,13 @@ AM_CONDITIONAL(HAVE_SPLINT, test -n "${SPLINT}")
# this function checks if CC support options passed as
# args. Global CFLAGS are ignored during this test.
cc_supports_flag() {
local CPPFLAGS="$CPPFLAGS $@"
BACKUP="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $@"
AC_MSG_CHECKING([whether $CC supports "$@"])
AC_PREPROC_IFELSE([AC_LANG_PROGRAM([])],
[RC=0; AC_MSG_RESULT([yes])],
[RC=1; AC_MSG_RESULT([no])])
CPPFLAGS="$BACKUP"
return $RC
}
@ -94,10 +100,15 @@ case $exec_prefix in
esac
# Checks for libraries.
AC_CHECK_LIB([rt], [mq_open])
AC_CHECK_LIB([dl], [dlopen])
AC_CHECK_LIB([pthread], [pthread_create])
AC_CHECK_LIB([socket], [socket])
dnl librt from glibc NEEDs libpthread
dnl so. if test for libpthread after librt
dnl it will always be "none needed", but it is not true
dnl when linking libraries. Looks like a bug.
AC_SEARCH_LIBS([pthread_create], [pthread])
AC_SEARCH_LIBS([mq_open], [rt])
AC_SEARCH_LIBS([dlopen], [dl])
AC_SEARCH_LIBS([socket], [socket])
AC_SEARCH_LIBS([gethostbyname], [nsl])
# look for testing harness "check"
PKG_CHECK_MODULES([CHECK], [check >= 0.9.4],[with_check=yes],[with_check=no])
@ -116,11 +127,13 @@ fi
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_CHECK_HEADERS([arpa/inet.h link.h fcntl.h inttypes.h limits.h netinet/in.h stdint.h \
dlfcn.h time.h sys/time.h stdlib.h string.h strings.h sys/types.h sys/stat.h \
sys/param.h sys/socket.h sys/time.h sys/poll.h sys/epoll.h sys/uio.h \
sys/sockio.h sys/un.h sys/resource.h syslog.h errno.h unistd.h sys/mman.h \
sys/sem.h sys/ipc.h sys/msg.h mqueue.h])
AC_CHECK_HEADERS([arpa/inet.h link.h fcntl.h inttypes.h limits.h netinet/in.h \
stdint.h stddef.h stdlib.h string.h strings.h \
dlfcn.h time.h sys/time.h sys/types.h sys/stat.h \
sys/param.h sys/socket.h sys/time.h sys/poll.h sys/epoll.h \
sys/uio.h sys/event.h sys/sockio.h sys/un.h sys/resource.h \
syslog.h errno.h unistd.h sys/mman.h \
sys/sem.h sys/ipc.h sys/msg.h netdb.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_UID_T
@ -132,19 +145,59 @@ AC_TYPE_MODE_T
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
AC_TYPE_UINT32_T
AC_TYPE_UINT64_T
AC_TYPE_UINT32_T
AC_TYPE_UINT16_T
AC_TYPE_UINT8_T
AC_CHECK_MEMBER([struct sockaddr_un.sun_len],
[AC_DEFINE([HAVE_STRUCT_SOCKADDR_UN_SUN_LEN],
1,
[Define to 1 if struct sockaddr_un has a member sun_len])],
[],
[#include <sys/un.h>])
AC_MSG_CHECKING(looking for union semun in sys/sem.h)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
[[#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>]],
[[union semun arg; semctl(0, 0, 0, arg);]])],
[
AC_MSG_RESULT([yes])
AC_DEFINE_UNQUOTED([HAVE_SEMUN], 1, [Define to 1 if you have union semun.])
],
[
AC_MSG_RESULT([no])
]
)
# Checks for library functions.
AC_FUNC_CHOWN
AC_FUNC_FORK
AC_FUNC_MMAP
AC_CHECK_FUNCS([alarm clock_gettime ftruncate gettimeofday localtime localtime_r \
memset munmap socket strchr strrchr strdup strerror strstr \
poll epoll_create epoll_create1 random rand getrlimit sysconf \
AC_FUNC_STRERROR_R
AC_CHECK_FUNCS([alarm clock_gettime ftruncate gettimeofday \
localtime localtime_r memset munmap socket \
strchr strrchr strdup strstr strcasecmp \
poll epoll_create epoll_create1 kqueue \
random rand getrlimit sysconf \
pthread_spin_lock pthread_setschedparam \
sched_get_priority_max sched_setscheduler])
pthread_mutexattr_setpshared \
pthread_condattr_setpshared \
sem_timedwait semtimedop \
sched_get_priority_max sched_setscheduler \
getpeerucred getpeereid])
AM_CONDITIONAL(HAVE_SEM_TIMEDWAIT,
[test "x$ac_cv_func_sem_timedwait" = xyes])
AM_CONDITIONAL(HAVE_EPOLL,
[test "x$ac_cv_func_epoll_create" = xyes])
AM_CONDITIONAL(HAVE_POLL,
[test "x$ac_cv_func_poll" = xyes])
AM_CONDITIONAL(HAVE_KQUEUE,
[test "x$ac_cv_func_kqueue" = xyes])
AC_CONFIG_LIBOBJ_DIR(lib)
AC_REPLACE_FUNCS(strlcpy strlcat strchrnul)
@ -152,9 +205,6 @@ AC_REPLACE_FUNCS(strlcpy strlcat strchrnul)
## local defines
PACKAGE_FEATURES=""
if test x$ac_cv_func_timerfd_create = xyes; then
PACKAGE_FEATURES="$PACKAGE_FEATURES timerfd"
fi
if test x$ac_cv_func_epoll_create = xyes; then
PACKAGE_FEATURES="$PACKAGE_FEATURES epoll"
fi
@ -209,9 +259,6 @@ fi
# OS detection
# THIS SECTION MUST DIE!
CP=cp
LIB_RT=-lrt
supports_sysv_mq="yes"
supports_posix_mq="yes"
AC_MSG_CHECKING([for os in ${host_os}])
case "$host_os" in
*linux*)
@ -219,22 +266,24 @@ case "$host_os" in
[Compiling for Linux platform])
AC_MSG_RESULT([Linux])
;;
*cygwin*)
AC_DEFINE_UNQUOTED([QB_CYGWIN], [1],
[Compiling for Cygwin platform])
ac_cv_link_attribute_section=no
nongcc_memory_barrier_needed=yes
gcc_has_builtin_atomic_operations=no
AC_MSG_RESULT([Cygwin])
;;
darwin*)
AC_DEFINE_UNQUOTED([QB_DARWIN], [1],
[Compiling for Darwin platform])
CP=rsync
LIB_RT=
supports_sysv_mq="no"
supports_posix_mq="no"
ac_cv_link_attribute_section=no
dnl Attribute section appears to work here but fails later with:
dnl cc1: error in backend: Global variable 'descriptor.4902' has an invalid section specifier '__verbose': mach-o section specifier requires a segment and section separated by a comma
AC_DEFINE_UNQUOTED([MAP_ANONYMOUS], [MAP_ANON],
[Shared memory define for Darwin platform])
AC_DEFINE_UNQUOTED([PATH_MAX], [4096],
[Number of chars in a path name including nul])
AC_DEFINE_UNQUOTED([NAME_MAX], [255],
[Number of chars in a file name])
dnl cc1: error in backend: Global variable 'descriptor.4902'
dnl has an invalid section specifier '__verbose': mach-o
dnl section specifier requires a segment and section
dnl separated by a comma
AC_DEFINE_UNQUOTED([DISABLE_POSIX_THREAD_PROCESS_SHARED], [1],
[Disable _POSIX_THREAD_PROCESS_SHARED])
AC_MSG_RESULT([Dawin])
@ -242,8 +291,6 @@ case "$host_os" in
*bsd*)
AC_DEFINE_UNQUOTED([QB_BSD], [1],
[Compiling for BSD platform])
AC_DEFINE_UNQUOTED([MAP_ANONYMOUS], [MAP_ANON],
[Shared memory define for Darwin platform])
case "$host_os" in
*freebsd[[234567]]*)
;;
@ -251,16 +298,26 @@ case "$host_os" in
AC_DEFINE_UNQUOTED([QB_FREEBSD_GE_8], [1],
[Compiling for FreeBSD >= 8 platform])
;;
*netbsd*)
# this is because dlopen within a dl_iterate_phdr
# callback locks up.
ac_cv_link_attribute_section=no
AC_DEFINE_UNQUOTED([UNIX_PATH_MAX], [103],
[Unix path length])
;;
*openbsd*)
AC_DEFINE_UNQUOTED([UNIX_PATH_MAX], [104],
[Unix path length])
;;
esac
AC_MSG_RESULT([BSD])
;;
*solaris*)
ac_cv_link_attribute_section=no
AC_DEFINE_UNQUOTED(DISABLE_IPC_SHM, 1,
[Disable shared mem ipc])
AC_DEFINE_UNQUOTED([QB_SOLARIS], [1],
[Compiling for Solaris platform])
AC_DEFINE_UNQUOTED([TS_CLASS], [1],
[Prevent being scheduled RR])
AC_DEFINE_UNQUOTED([_SEM_SEMUN_UNDEFINED], [1],
[The semun structure is undefined])
CP=rsync
AC_MSG_RESULT([Solaris])
;;
@ -345,7 +402,6 @@ AC_ARG_WITH([socket-dir],
[ SOCKETDIR="$localstatedir/run" ])
AC_SUBST(CP)
AC_SUBST(LIB_RT)
# *FLAGS handling goes here
ENV_CFLAGS="$CFLAGS"
@ -414,28 +470,6 @@ if test "x${enable_slow_tests}" = xyes ; then
fi
AM_CONDITIONAL(HAVE_SLOW_TESTS, [test "x${enable_slow_tests}" = xyes])
if test -n "$ac_cv_supports_sysv_mq"; then
supports_sysv_mq=$ac_cv_supports_sysv_mq
fi
if test "x${supports_sysv_mq}" = xyes ; then
AC_DEFINE([HAVE_SYSV_MQ], [1],
[have sysv message queues])
PACKAGE_FEATURES="$PACKAGE_FEATURES sysv_mq"
AC_MSG_NOTICE([Enabling SYSV Message Queues])
fi
AM_CONDITIONAL(HAVE_SYSV_MQ, [test "x${supports_sysv_mq}" = xyes])
if test -n "$ac_cv_supports_posix_mq"; then
supports_posix_mq=$ac_cv_supports_posix_mq
fi
if test "x${supports_posix_mq}" = xyes ; then
AC_DEFINE([HAVE_POSIX_MQ], [1],
[have posix message queues])
PACKAGE_FEATURES="$PACKAGE_FEATURES posix_mq"
AC_MSG_NOTICE([Enabling POSIX Message Queues])
fi
AM_CONDITIONAL(HAVE_POSIX_MQ, [test "x${supports_posix_mq}" = xyes])
# --- callsite sections ---
if test "x${GCC}" = xyes; then
AC_MSG_CHECKING([whether GCC supports __attribute__((section())])
@ -504,6 +538,7 @@ AC_CONFIG_FILES([Makefile
include/qb/Makefile
lib/Makefile
lib/libqb.pc
tools/Makefile
tests/Makefile
examples/Makefile
docs/Makefile

View File

@ -27,7 +27,7 @@ dependant_headers = $(wildcard $(inc_dir)/qb*.h)
dist_man_MANS = man3/qbipcc.h.3 man3/qbipcs.h.3 man3/qbatomic.h.3 \
man3/qbhdb.h.3 man3/qbipc_common.h.3 man3/qblist.h.3 \
man3/qbloop.h.3 man3/qbutil.h.3 man3/qbarray.h.3 \
man3/qblog.h.3 man3/qbmap.h.3
man3/qblog.h.3 man3/qbmap.h.3 man8/qb-blackbox.8
$(dist_man_MANS): man.dox $(dependant_headers)

View File

@ -105,7 +105,8 @@ am__uninstall_files_from_dir = { \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
man3dir = $(mandir)/man3
am__installdirs = "$(DESTDIR)$(man3dir)"
am__installdirs = "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(man8dir)"
man8dir = $(mandir)/man8
NROFF = nroff
MANS = $(dist_man_MANS)
HEADERS = $(noinst_HEADERS)
@ -158,7 +159,6 @@ LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIB_RT = @LIB_RT@
LINT_FLAGS = @LINT_FLAGS@
LIPO = @LIPO@
LN_S = @LN_S@
@ -253,7 +253,7 @@ noinst_HEADERS = mainpage.h
@HAVE_DOXYGEN_TRUE@dist_man_MANS = man3/qbipcc.h.3 man3/qbipcs.h.3 man3/qbatomic.h.3 \
@HAVE_DOXYGEN_TRUE@ man3/qbhdb.h.3 man3/qbipc_common.h.3 man3/qblist.h.3 \
@HAVE_DOXYGEN_TRUE@ man3/qbloop.h.3 man3/qbutil.h.3 man3/qbarray.h.3 \
@HAVE_DOXYGEN_TRUE@ man3/qblog.h.3 man3/qbmap.h.3
@HAVE_DOXYGEN_TRUE@ man3/qblog.h.3 man3/qbmap.h.3 man8/qb-blackbox.8
all: all-am
@ -334,6 +334,42 @@ uninstall-man3:
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
dir='$(DESTDIR)$(man3dir)'; $(am__uninstall_files_from_dir)
install-man8: $(dist_man_MANS)
@$(NORMAL_INSTALL)
test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)"
@list=''; test -n "$(man8dir)" || exit 0; \
{ for i in $$list; do echo "$$i"; done; \
l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
sed -n '/\.8[a-z]*$$/p'; \
} | while read p; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; echo "$$p"; \
done | \
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
sed 'N;N;s,\n, ,g' | { \
list=; while read file base inst; do \
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \
fi; \
done; \
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
while read files; do \
test -z "$$files" || { \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \
done; }
uninstall-man8:
@$(NORMAL_UNINSTALL)
@list=''; test -n "$(man8dir)" || exit 0; \
files=`{ for i in $$list; do echo "$$i"; done; \
l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \
sed -n '/\.8[a-z]*$$/p'; \
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir)
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
@ -434,7 +470,7 @@ check-am: all-am
check: check-am
all-am: Makefile $(MANS) $(HEADERS)
installdirs:
for dir in "$(DESTDIR)$(man3dir)"; do \
for dir in "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(man8dir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
@ -502,7 +538,7 @@ install-info: install-info-am
install-info-am:
install-man: install-man3
install-man: install-man3 install-man8
install-pdf: install-pdf-am
@ -532,7 +568,7 @@ ps-am:
uninstall-am: uninstall-man
uninstall-man: uninstall-man3
uninstall-man: uninstall-man3 uninstall-man8
.MAKE: install-am install-strip
@ -542,12 +578,13 @@ uninstall-man: uninstall-man3
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-man3 install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
installcheck installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-generic \
mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
uninstall-am uninstall-man uninstall-man3
install-info-am install-man install-man3 install-man8 \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags uninstall uninstall-am uninstall-man uninstall-man3 \
uninstall-man8
@HAVE_DOXYGEN_TRUE@$(dist_man_MANS): man.dox $(dependant_headers)

View File

@ -1,6 +1,6 @@
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = libqb
PROJECT_NUMBER = 0.11.1
PROJECT_NUMBER = 0.14.2
OUTPUT_DIRECTORY = .
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
@ -60,7 +60,6 @@ GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_DIRECTORIES = NO
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =

View File

@ -60,7 +60,6 @@ GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_DIRECTORIES = NO
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =

View File

@ -3,11 +3,13 @@
*
* @section overview Overview
*
* libqb is a thread-safe library with the primary purpose of providing high performance client server reusable features.
* libqb is a thread-safe library with the primary purpose of providing high
* performance client server reusable features.
*
* It provides high performance ipc, and poll.
*
* We don't intend be an all encompassing library, but instead provide very specially focused APIs that are highly
* We don't intend be an all encompassing library, but instead provide very
* specially focused APIs that are highly
*
* tuned for maximum performance for client/server applications.
*
@ -74,8 +76,6 @@
* and service applications. It supports many features including:
* - Multiple transport implementations
* -# Shared memory implementation for very high performance.
* -# Posix Message queues
* -# SysV Message queues
* -# Unix sockets
* - A synchronous request/response channel and asynchronous response channel per ipc connection.
* - User defined private data per IPC connection.

View File

@ -1,6 +1,6 @@
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = libqb
PROJECT_NUMBER = 0.11.1
PROJECT_NUMBER = 0.14.2
OUTPUT_DIRECTORY = .
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
@ -60,7 +60,6 @@ GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_DIRECTORIES = NO
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =

View File

@ -60,7 +60,6 @@ GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_DIRECTORIES = NO
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =

View File

@ -1,4 +1,4 @@
.TH "qbarray.h" 3 "Sun Mar 11 2012" "Version 0.11.1" "libqb" \" -*- nroff -*-
.TH "qbarray.h" 3 "Mon Sep 10 2012" "Version 0.14.2" "libqb" \" -*- nroff -*-
.ad l
.nh
.SH NAME
@ -62,13 +62,13 @@ This is a dynamic array (it can grow, but without moving memory)\&.
.PP
.nf
arr = qb_array_create_2(64, sizeof(struct my_struct), 256);
\&.\&.\&.
res = qb_array_index(arr, idx, (void**)&my_ptr);
if (res < 0) {
arr = qb_array_create_2(64, sizeof(struct my_struct), 256);
\&.\&.\&.
res = qb_array_index(arr, idx, (void**)&my_ptr);
if (res < 0) {
return res;
}
// use my_ptr, now even if there is a grow, this pointer will be valid\&.
}
// use my_ptr, now even if there is a grow, this pointer will be valid\&.
.fi
.PP
@ -80,7 +80,7 @@ This is a dynamic array (it can grow, but without moving memory)\&.
This is an opaque data type representing an instance of an array\&.
.SH "Function Documentation"
.PP
.SS "\fBqb_array_t\fP* \fBqb_array_create\fP (size_tmax_elements, size_telement_size)"
.SS "\fBqb_array_t\fP* qb_array_create (size_tmax_elements, size_telement_size)"
.PP
Create an array with fixed sized elements\&. \fBParameters:\fP
@ -96,7 +96,7 @@ array instance\&.
.RE
.PP
.SS "\fBqb_array_t\fP* \fBqb_array_create_2\fP (size_tmax_elements, size_telement_size, size_tautogrow_elements)"
.SS "\fBqb_array_t\fP* qb_array_create_2 (size_tmax_elements, size_telement_size, size_tautogrow_elements)"
.PP
Create an array with fixed sized elements\&. \fBParameters:\fP
@ -114,11 +114,11 @@ array instance\&.
.RE
.PP
.SS "size_t \fBqb_array_elems_per_bin_get\fP (\fBqb_array_t\fP *a)"
.SS "size_t qb_array_elems_per_bin_get (\fBqb_array_t\fP *a)"
.PP
Get the number of elements per bin\&.
.SS "void \fBqb_array_free\fP (\fBqb_array_t\fP *a)"
.SS "void qb_array_free (\fBqb_array_t\fP *a)"
.PP
Free all the memory used by the array\&. \fBParameters:\fP
@ -127,7 +127,7 @@ Free all the memory used by the array\&. \fBParameters:\fP
.RE
.PP
.SS "int32_t \fBqb_array_grow\fP (\fBqb_array_t\fP *a, size_tmax_elements)"
.SS "int32_t qb_array_grow (\fBqb_array_t\fP *a, size_tmax_elements)"
.PP
Grow the array\&. \fBParameters:\fP
@ -143,7 +143,7 @@ Grow the array\&. \fBParameters:\fP
.RE
.PP
.SS "int32_t \fBqb_array_index\fP (\fBqb_array_t\fP *a, int32_tidx, void **element_out)"
.SS "int32_t qb_array_index (\fBqb_array_t\fP *a, int32_tidx, void **element_out)"
.PP
Get an element at a particular index\&. \fBParameters:\fP
@ -161,7 +161,7 @@ Get an element at a particular index\&. \fBParameters:\fP
.RE
.PP
.SS "size_t \fBqb_array_num_bins_get\fP (\fBqb_array_t\fP *a)"
.SS "size_t qb_array_num_bins_get (\fBqb_array_t\fP *a)"
.PP
Get the number of bins used or the array\&.

View File

@ -1,4 +1,4 @@
.TH "qbatomic.h" 3 "Sun Mar 11 2012" "Version 0.11.1" "libqb" \" -*- nroff -*-
.TH "qbatomic.h" 3 "Mon Sep 10 2012" "Version 0.14.2" "libqb" \" -*- nroff -*-
.ad l
.nh
.SH NAME
@ -16,7 +16,7 @@ Basic atomic integer and pointer operations\&.
\fC#include <qb/qbconfig\&.h>\fP
.br
.SS "Defines"
.SS "Macros"
.in +1c
.ti -1c
@ -92,9 +92,9 @@ You must not directly read integers or pointers concurrently accessed by multipl
If you are using those functions for anything apart from simple reference counting, you should really be aware of the implications of doing that\&. There are literally thousands of ways to shoot yourself in the foot\&. So if in doubt, use a pthread_mutex\&. If you don't know, what memory barriers are, do not use anything but \fBqb_atomic_int_inc()\fP and \fBqb_atomic_int_dec_and_test()\fP\&.
.PP
It is not safe to set an integer or pointer just by assigning to it, when it is concurrently accessed by other threads with the following functions\&. Use \fBqb_atomic_int_compare_and_exchange()\fP or \fBqb_atomic_pointer_compare_and_exchange()\fP respectively\&.
.SH "Define Documentation"
.SH "Macro Definition Documentation"
.PP
.SS "#define \fBqb_atomic_int_dec_and_test\fP(atomic) (\fBqb_atomic_int_exchange_and_add\fP ((atomic), -1) == 1)"
.SS "#define qb_atomic_int_dec_and_test(atomic) (\fBqb_atomic_int_exchange_and_add\fP ((atomic), -1) == 1)"
.PP
Atomically decrements the integer pointed to by atomic by 1\&. \fBParameters:\fP
@ -108,14 +108,14 @@ QB_TRUE if the integer pointed to by atomic is 0 after decrementing it
.RE
.PP
.SS "#define \fBqb_atomic_int_get\fP(atomic)"
.SS "#define qb_atomic_int_get(atomic)"
\fBValue:\fP
.PP
.nf
((void) sizeof (char* [sizeof (*(atomic)) == sizeof (int32_t) ? 1 : -1]), \
(qb_atomic_int_get) ((volatile int32_t QB_GNUC_MAY_ALIAS *) (volatile void *) (atomic)))
.fi
.SS "#define \fBqb_atomic_int_inc\fP(atomic) (\fBqb_atomic_int_add\fP ((atomic), 1))"
.SS "#define qb_atomic_int_inc(atomic) (\fBqb_atomic_int_add\fP ((atomic), 1))"
.PP
Atomically increments the integer pointed to by atomic by 1\&. \fBParameters:\fP
@ -124,21 +124,21 @@ Atomically increments the integer pointed to by atomic by 1\&. \fBParameters:\fP
.RE
.PP
.SS "#define \fBqb_atomic_int_set\fP(atomic, newval)"
.SS "#define qb_atomic_int_set(atomic, newval)"
\fBValue:\fP
.PP
.nf
((void) sizeof (char* [sizeof (*(atomic)) == sizeof (int32_t) ? 1 : -1]), \
(qb_atomic_int_set) ((volatile int32_t QB_GNUC_MAY_ALIAS *) (volatile void *) (atomic), (newval)))
.fi
.SS "#define \fBqb_atomic_pointer_get\fP(atomic)"
.SS "#define qb_atomic_pointer_get(atomic)"
\fBValue:\fP
.PP
.nf
((void) sizeof (char* [sizeof (*(atomic)) == sizeof (void*) ? 1 : -1]), \
(qb_atomic_pointer_get) ((volatile void* QB_GNUC_MAY_ALIAS *) (volatile void *) (atomic)))
.fi
.SS "#define \fBqb_atomic_pointer_set\fP(atomic, newval)"
.SS "#define qb_atomic_pointer_set(atomic, newval)"
\fBValue:\fP
.PP
.nf
@ -147,9 +147,9 @@ Atomically increments the integer pointed to by atomic by 1\&. \fBParameters:\fP
.fi
.SH "Function Documentation"
.PP
.SS "void \fBqb_atomic_init\fP (void)"
.SS "void qb_atomic_init (void)"
.SS "void \fBqb_atomic_int_add\fP (volatile int32_t \fBQB_GNUC_MAY_ALIAS\fP *atomic, int32_tval)"
.SS "void qb_atomic_int_add (volatile int32_t \fBQB_GNUC_MAY_ALIAS\fP *atomic, int32_tval)"
.PP
Atomically adds val to the integer pointed to by atomic\&. Also acts as a memory barrier\&.
@ -162,7 +162,7 @@ Atomically adds val to the integer pointed to by atomic\&. Also acts as a memory
.RE
.PP
.SS "int32_t \fBqb_atomic_int_compare_and_exchange\fP (volatile int32_t \fBQB_GNUC_MAY_ALIAS\fP *atomic, int32_toldval, int32_tnewval)"
.SS "int32_t qb_atomic_int_compare_and_exchange (volatile int32_t \fBQB_GNUC_MAY_ALIAS\fP *atomic, int32_toldval, int32_tnewval)"
.PP
Compares oldval with the integer pointed to by atomic and if they are equal, atomically exchanges *atomic with newval\&. Also acts as a memory barrier\&.
@ -182,7 +182,7 @@ QB_TRUE, if *atomic was equal oldval\&. QB_FALSE otherwise\&.
.RE
.PP
.SS "int32_t \fBqb_atomic_int_exchange_and_add\fP (volatile int32_t \fBQB_GNUC_MAY_ALIAS\fP *atomic, int32_tval)"
.SS "int32_t qb_atomic_int_exchange_and_add (volatile int32_t \fBQB_GNUC_MAY_ALIAS\fP *atomic, int32_tval)"
.PP
Atomically adds val to the integer pointed to by atomic\&. It returns the value of *atomic just before the addition took place\&. Also acts as a memory barrier\&.
@ -200,7 +200,7 @@ the value of *atomic before the addition\&.
.RE
.PP
.SS "int32_t \fBqb_atomic_int_get\fP (volatile int32_t \fBQB_GNUC_MAY_ALIAS\fP *atomic)"
.SS "int32_t qb_atomic_int_get (volatile int32_t \fBQB_GNUC_MAY_ALIAS\fP *atomic)"
.PP
Reads the value of the integer pointed to by atomic\&. Also acts as a memory barrier\&.
@ -216,7 +216,7 @@ the value of atomic
.RE
.PP
.SS "void \fBqb_atomic_int_set\fP (volatile int32_t \fBQB_GNUC_MAY_ALIAS\fP *atomic, int32_tnewval)"
.SS "void qb_atomic_int_set (volatile int32_t \fBQB_GNUC_MAY_ALIAS\fP *atomic, int32_tnewval)"
.PP
Sets the value of the integer pointed to by atomic\&. Also acts as a memory barrier\&.
@ -229,7 +229,7 @@ Sets the value of the integer pointed to by atomic\&. Also acts as a memory barr
.RE
.PP
.SS "int32_t \fBqb_atomic_pointer_compare_and_exchange\fP (volatile void *\fBQB_GNUC_MAY_ALIAS\fP *atomic, void *oldval, void *newval)"
.SS "int32_t qb_atomic_pointer_compare_and_exchange (volatile void *\fBQB_GNUC_MAY_ALIAS\fP *atomic, void *oldval, void *newval)"
.PP
Compares oldval with the pointer pointed to by atomic and if they are equal, atomically exchanges *atomic with newval\&. Also acts as a memory barrier\&.
@ -249,7 +249,7 @@ QB_TRUE if atomic was equal oldval, else QB_FALSE\&.
.RE
.PP
.SS "void* \fBqb_atomic_pointer_get\fP (volatile void *\fBQB_GNUC_MAY_ALIAS\fP *atomic)"
.SS "void* qb_atomic_pointer_get (volatile void *\fBQB_GNUC_MAY_ALIAS\fP *atomic)"
.PP
Reads the value of the pointer pointed to by atomic\&. Also acts as a memory barrier\&.
@ -265,7 +265,7 @@ the value to add to atomic\&.
.RE
.PP
.SS "void \fBqb_atomic_pointer_set\fP (volatile void *\fBQB_GNUC_MAY_ALIAS\fP *atomic, void *newval)"
.SS "void qb_atomic_pointer_set (volatile void *\fBQB_GNUC_MAY_ALIAS\fP *atomic, void *newval)"
.PP
Sets the value of the pointer pointed to by atomic\&. Also acts as a memory barrier\&.

View File

@ -1,4 +1,4 @@
.TH "qbhdb.h" 3 "Sun Mar 11 2012" "Version 0.11.1" "libqb" \" -*- nroff -*-
.TH "qbhdb.h" 3 "Mon Sep 10 2012" "Version 0.14.2" "libqb" \" -*- nroff -*-
.ad l
.nh
.SH NAME
@ -28,7 +28,7 @@ The handle database is for reference counting objects\&.
.RI "struct \fBqb_hdb\fP"
.br
.in -1c
.SS "Defines"
.SS "Macros"
.in +1c
.ti -1c
@ -108,13 +108,13 @@ The handle database is for reference counting objects\&.
The handle database is for reference counting objects\&.
.SH "Define Documentation"
.SH "Macro Definition Documentation"
.PP
.SS "#define \fB_GNU_SOURCE\fP"
.SS "#define _GNU_SOURCE"
.SS "#define \fBQB_HDB_D_FORMAT\fP '%'PRIu64"
.SS "#define QB_HDB_D_FORMAT '%'PRIu64"
.SS "#define \fBQB_HDB_DECLARE\fP(database_name, destructor_function)"
.SS "#define QB_HDB_DECLARE(database_name, destructor_function)"
\fBValue:\fP
.PP
.nf
@ -129,11 +129,11 @@ static struct qb_hdb (database_name) = { \
.PP
Convience macro for declaring a file scoped handle database\&. .PP
.nf
QB_HDB_DECLARE(my_handle_database, NULL);
QB_HDB_DECLARE(my_handle_database, NULL);
.fi
.PP
.SS "#define \fBQB_HDB_X_FORMAT\fP '%'PRIx64"
.SS "#define QB_HDB_X_FORMAT '%'PRIx64"
.SH "Typedef Documentation"
.PP
@ -143,9 +143,9 @@ Convience macro for declaring a file scoped handle database\&. .PP
Generic handle type is 64 bits\&.
.SH "Function Documentation"
.PP
.SS "uint32_t \fBqb_hdb_base_convert\fP (\fBqb_handle_t\fPhandle)"
.SS "uint32_t qb_hdb_base_convert (\fBqb_handle_t\fPhandle)"
.SS "void \fBqb_hdb_create\fP (struct \fBqb_hdb\fP *hdb)"
.SS "void qb_hdb_create (struct \fBqb_hdb\fP *hdb)"
.PP
Create a new database\&. \fBParameters:\fP
@ -154,7 +154,7 @@ Create a new database\&. \fBParameters:\fP
.RE
.PP
.SS "void \fBqb_hdb_destroy\fP (struct \fBqb_hdb\fP *hdb)"
.SS "void qb_hdb_destroy (struct \fBqb_hdb\fP *hdb)"
.PP
Destroy a handle database\&. \fBParameters:\fP
@ -163,7 +163,7 @@ Destroy a handle database\&. \fBParameters:\fP
.RE
.PP
.SS "int32_t \fBqb_hdb_handle_create\fP (struct \fBqb_hdb\fP *hdb, int32_tinstance_size, \fBqb_handle_t\fP *handle_id_out)"
.SS "int32_t qb_hdb_handle_create (struct \fBqb_hdb\fP *hdb, int32_tinstance_size, \fBqb_handle_t\fP *handle_id_out)"
.PP
Create a new handle\&. \fBParameters:\fP
@ -181,7 +181,7 @@ Create a new handle\&. \fBParameters:\fP
.RE
.PP
.SS "int32_t \fBqb_hdb_handle_destroy\fP (struct \fBqb_hdb\fP *hdb, \fBqb_handle_t\fPhandle_in)"
.SS "int32_t qb_hdb_handle_destroy (struct \fBqb_hdb\fP *hdb, \fBqb_handle_t\fPhandle_in)"
.PP
Request the destruction of the object\&. When the refcount is 0, it will be destroyed\&.
@ -199,7 +199,7 @@ Request the destruction of the object\&. When the refcount is 0, it will be dest
.RE
.PP
.SS "int32_t \fBqb_hdb_handle_get\fP (struct \fBqb_hdb\fP *hdb, \fBqb_handle_t\fPhandle_in, void **instance)"
.SS "int32_t qb_hdb_handle_get (struct \fBqb_hdb\fP *hdb, \fBqb_handle_t\fPhandle_in, void **instance)"
.PP
Get the instance associated with this handle and increase it's refcount\&. \fBParameters:\fP
@ -217,7 +217,7 @@ Get the instance associated with this handle and increase it's refcount\&. \fBPa
.RE
.PP
.SS "int32_t \fBqb_hdb_handle_get_always\fP (struct \fBqb_hdb\fP *hdb, \fBqb_handle_t\fPhandle_in, void **instance)"
.SS "int32_t qb_hdb_handle_get_always (struct \fBqb_hdb\fP *hdb, \fBqb_handle_t\fPhandle_in, void **instance)"
.PP
Get the instance associated with this handle and increase it's refcount\&. \fBParameters:\fP
@ -235,7 +235,7 @@ Get the instance associated with this handle and increase it's refcount\&. \fBPa
.RE
.PP
.SS "int32_t \fBqb_hdb_handle_put\fP (struct \fBqb_hdb\fP *hdb, \fBqb_handle_t\fPhandle_in)"
.SS "int32_t qb_hdb_handle_put (struct \fBqb_hdb\fP *hdb, \fBqb_handle_t\fPhandle_in)"
.PP
Put the instance associated with this handle and decrease it's refcount\&. \fBParameters:\fP
@ -251,7 +251,7 @@ Put the instance associated with this handle and decrease it's refcount\&. \fBPa
.RE
.PP
.SS "int32_t \fBqb_hdb_handle_refcount_get\fP (struct \fBqb_hdb\fP *hdb, \fBqb_handle_t\fPhandle_in)"
.SS "int32_t qb_hdb_handle_refcount_get (struct \fBqb_hdb\fP *hdb, \fBqb_handle_t\fPhandle_in)"
.PP
Get the current refcount\&. \fBParameters:\fP
@ -267,7 +267,7 @@ Get the current refcount\&. \fBParameters:\fP
.RE
.PP
.SS "int32_t \fBqb_hdb_iterator_next\fP (struct \fBqb_hdb\fP *hdb, void **instance, \fBqb_handle_t\fP *handle)"
.SS "int32_t qb_hdb_iterator_next (struct \fBqb_hdb\fP *hdb, void **instance, \fBqb_handle_t\fP *handle)"
.PP
Get the next object and increament it's refcount\&. Remember to call \fBqb_hdb_handle_put()\fP
@ -287,7 +287,7 @@ Get the next object and increament it's refcount\&. Remember to call \fBqb_hdb_h
.RE
.PP
.SS "void \fBqb_hdb_iterator_reset\fP (struct \fBqb_hdb\fP *hdb)"
.SS "void qb_hdb_iterator_reset (struct \fBqb_hdb\fP *hdb)"
.PP
Reset the iterator\&. \fBParameters:\fP
@ -296,7 +296,7 @@ Reset the iterator\&. \fBParameters:\fP
.RE
.PP
.SS "uint64_t \fBqb_hdb_nocheck_convert\fP (uint32_thandle)"
.SS "uint64_t qb_hdb_nocheck_convert (uint32_thandle)"
.SH "Author"
.PP

View File

@ -1,4 +1,4 @@
.TH "qbipc_common.h" 3 "Sun Mar 11 2012" "Version 0.11.1" "libqb" \" -*- nroff -*-
.TH "qbipc_common.h" 3 "Mon Sep 10 2012" "Version 0.14.2" "libqb" \" -*- nroff -*-
.ad l
.nh
.SH NAME
@ -19,7 +19,7 @@ qbipc_common.h \-
.RI "struct \fBqb_ipc_response_header\fP"
.br
.in -1c
.SS "Defines"
.SS "Macros"
.in +1c
.ti -1c
@ -42,7 +42,7 @@ qbipc_common.h \-
.in +1c
.ti -1c
.RI "enum \fBqb_ipc_type\fP { \fBQB_IPC_SOCKET\fP, \fBQB_IPC_SHM\fP, \fBQB_IPC_POSIX_MQ\fP, \fBQB_IPC_SYSV_MQ\fP }"
.RI "enum \fBqb_ipc_type\fP { \fBQB_IPC_SOCKET\fP, \fBQB_IPC_SHM\fP, \fBQB_IPC_POSIX_MQ\fP, \fBQB_IPC_SYSV_MQ\fP, \fBQB_IPC_NATIVE\fP }"
.br
.in -1c
.SS "Functions"
@ -59,17 +59,17 @@ qbipc_common.h \-
.RI "enum \fBqb_ipc_type\fP \fB__attribute__\fP"
.br
.in -1c
.SH "Define Documentation"
.SH "Macro Definition Documentation"
.PP
.SS "#define \fBQB_IPC_MSG_AUTHENTICATE\fP -1"
.SS "#define QB_IPC_MSG_AUTHENTICATE -1"
.SS "#define \fBQB_IPC_MSG_DISCONNECT\fP -3"
.SS "#define QB_IPC_MSG_DISCONNECT -3"
.SS "#define \fBQB_IPC_MSG_NEW_EVENT_SOCK\fP -2"
.SS "#define QB_IPC_MSG_NEW_EVENT_SOCK -2"
.SS "#define \fBQB_IPC_MSG_NEW_MESSAGE\fP 0"
.SS "#define QB_IPC_MSG_NEW_MESSAGE 0"
.SS "#define \fBQB_IPC_MSG_USER_START\fP \fBQB_IPC_MSG_NEW_MESSAGE\fP"
.SS "#define QB_IPC_MSG_USER_START \fBQB_IPC_MSG_NEW_MESSAGE\fP"
.SH "Enumeration Type Documentation"
.PP
@ -86,14 +86,16 @@ qbipc_common.h \-
\fB\fIQB_IPC_POSIX_MQ \fP\fP
.TP
\fB\fIQB_IPC_SYSV_MQ \fP\fP
.TP
\fB\fIQB_IPC_NATIVE \fP\fP
.SH "Function Documentation"
.PP
.SS "struct \fBqb_ipc_request_header\fP \fB__attribute__\fP ((aligned(8)))"
.SS "struct \fBqb_ipc_request_header\fP __attribute__ ((aligned(8)))"
.SH "Variable Documentation"
.PP
.SS "int32_t error \fB__attribute__\fP"
.SS "int32_t error __attribute__"
.SH "Author"
.PP

View File

@ -1,4 +1,4 @@
.TH "qbipcc.h" 3 "Sun Mar 11 2012" "Version 0.11.1" "libqb" \" -*- nroff -*-
.TH "qbipcc.h" 3 "Mon Sep 10 2012" "Version 0.14.2" "libqb" \" -*- nroff -*-
.ad l
.nh
.SH NAME
@ -76,6 +76,10 @@ Client IPC API\&.
.RI "void * \fBqb_ipcc_context_get\fP (\fBqb_ipcc_connection_t\fP *c)"
.br
.RI "\fIGet the context (set previously) \fP"
.ti -1c
.RI "int32_t \fBqb_ipcc_is_connected\fP (\fBqb_ipcc_connection_t\fP *c)"
.br
.RI "\fIIs the connection connected? \fP"
.in -1c
.SH "Detailed Description"
.PP
@ -108,7 +112,7 @@ The \fBqb_ipcc_event_recv()\fP function receives an out-of-band asyncronous mess
.SH "Function Documentation"
.PP
.SS "\fBqb_ipcc_connection_t\fP* \fBqb_ipcc_connect\fP (const char *name, size_tmax_msg_size)"
.SS "\fBqb_ipcc_connection_t\fP* qb_ipcc_connect (const char *name, size_tmax_msg_size)"
.PP
Create a connection to an IPC service\&. \fBParameters:\fP
@ -124,7 +128,7 @@ NULL (error: see errno) or a connection object\&.
.RE
.PP
.SS "void* \fBqb_ipcc_context_get\fP (\fBqb_ipcc_connection_t\fP *c)"
.SS "void* qb_ipcc_context_get (\fBqb_ipcc_connection_t\fP *c)"
.PP
Get the context (set previously) \fBParameters:\fP
@ -143,7 +147,7 @@ the context
.RE
.PP
.SS "void \fBqb_ipcc_context_set\fP (\fBqb_ipcc_connection_t\fP *c, void *context)"
.SS "void qb_ipcc_context_set (\fBqb_ipcc_connection_t\fP *c, void *context)"
.PP
Associate a 'user' pointer with this connection\&. \fBParameters:\fP
@ -159,7 +163,7 @@ Associate a 'user' pointer with this connection\&. \fBParameters:\fP
.RE
.PP
.SS "void \fBqb_ipcc_disconnect\fP (\fBqb_ipcc_connection_t\fP *c)"
.SS "void qb_ipcc_disconnect (\fBqb_ipcc_connection_t\fP *c)"
.PP
Disconnect an IPC connection\&. \fBParameters:\fP
@ -168,7 +172,7 @@ Disconnect an IPC connection\&. \fBParameters:\fP
.RE
.PP
.SS "ssize_t \fBqb_ipcc_event_recv\fP (\fBqb_ipcc_connection_t\fP *c, void *msg_ptr, size_tmsg_len, int32_tms_timeout)"
.SS "ssize_t qb_ipcc_event_recv (\fBqb_ipcc_connection_t\fP *c, void *msg_ptr, size_tmsg_len, int32_tms_timeout)"
.PP
Receive an event\&. \fBParameters:\fP
@ -186,11 +190,16 @@ Receive an event\&. \fBParameters:\fP
.PP
\fBReturns:\fP
.RS 4
size of the message or error (-errno)
size of the message or error (-errno)
.RE
.PP
\fBNote:\fP
.RS 4
that msg_ptr will include a \fBqb_ipc_response_header\fP at the top of the message\&.
.RE
.PP
.SS "int32_t \fBqb_ipcc_fc_enable_max_set\fP (\fBqb_ipcc_connection_t\fP *c, uint32_tmax)"
.SS "int32_t qb_ipcc_fc_enable_max_set (\fBqb_ipcc_connection_t\fP *c, uint32_tmax)"
.PP
Set the maximum allowable flowcontrol value\&. \fBNote:\fP
@ -206,7 +215,7 @@ the default is 1
.RE
.PP
.SS "int32_t \fBqb_ipcc_fd_get\fP (\fBqb_ipcc_connection_t\fP *c, int32_t *fd)"
.SS "int32_t qb_ipcc_fd_get (\fBqb_ipcc_connection_t\fP *c, int32_t *fd)"
.PP
Get the file descriptor to poll\&. \fBParameters:\fP
@ -217,7 +226,23 @@ Get the file descriptor to poll\&. \fBParameters:\fP
.RE
.PP
.SS "ssize_t \fBqb_ipcc_recv\fP (\fBqb_ipcc_connection_t\fP *c, void *msg_ptr, size_tmsg_len, int32_tms_timeout)"
.SS "int32_t qb_ipcc_is_connected (\fBqb_ipcc_connection_t\fP *c)"
.PP
Is the connection connected? \fBParameters:\fP
.RS 4
\fIc\fP connection instance
.RE
.PP
\fBReturn values:\fP
.RS 4
\fIQB_TRUE\fP when connected
.br
\fIQB_FALSE\fP when not connected
.RE
.PP
.SS "ssize_t qb_ipcc_recv (\fBqb_ipcc_connection_t\fP *c, void *msg_ptr, size_tmsg_len, int32_tms_timeout)"
.PP
Receive a response\&. \fBParameters:\fP
@ -233,11 +258,16 @@ Receive a response\&. \fBParameters:\fP
.PP
\fBReturns:\fP
.RS 4
(size recv'ed, -errno == error)
(size recv'ed, -errno == error)
.RE
.PP
\fBNote:\fP
.RS 4
that msg_ptr will include a \fBqb_ipc_response_header\fP at the top of the message\&.
.RE
.PP
.SS "ssize_t \fBqb_ipcc_send\fP (\fBqb_ipcc_connection_t\fP *c, const void *msg_ptr, size_tmsg_len)"
.SS "ssize_t qb_ipcc_send (\fBqb_ipcc_connection_t\fP *c, const void *msg_ptr, size_tmsg_len)"
.PP
Send a message\&. \fBParameters:\fP
@ -251,11 +281,16 @@ Send a message\&. \fBParameters:\fP
.PP
\fBReturns:\fP
.RS 4
(size sent, -errno == error)
(size sent, -errno == error)
.RE
.PP
\fBNote:\fP
.RS 4
the msg_ptr must include a \fBqb_ipc_request_header\fP at the top of the message\&. The server will read the size field to determine how much to recv\&.
.RE
.PP
.SS "ssize_t \fBqb_ipcc_sendv\fP (\fBqb_ipcc_connection_t\fP *c, const struct iovec *iov, size_tiov_len)"
.SS "ssize_t qb_ipcc_sendv (\fBqb_ipcc_connection_t\fP *c, const struct iovec *iov, size_tiov_len)"
.PP
Send a message (iovec)\&. \fBParameters:\fP
@ -269,11 +304,16 @@ Send a message (iovec)\&. \fBParameters:\fP
.PP
\fBReturns:\fP
.RS 4
(size sent, -errno == error)
(size sent, -errno == error)
.RE
.PP
\fBNote:\fP
.RS 4
the iov[0] must be a \fBqb_ipc_request_header\fP\&. The server will read the size field to determine how much to recv\&.
.RE
.PP
.SS "ssize_t \fBqb_ipcc_sendv_recv\fP (\fBqb_ipcc_connection_t\fP *c, const struct iovec *iov, uint32_tiov_len, void *msg_ptr, size_tmsg_len, int32_tms_timeout)"
.SS "ssize_t qb_ipcc_sendv_recv (\fBqb_ipcc_connection_t\fP *c, const struct iovec *iov, uint32_tiov_len, void *msg_ptr, size_tmsg_len, int32_tms_timeout)"
.PP
This is a convenience function that simply sends and then recvs\&. \fBParameters:\fP
@ -291,6 +331,13 @@ This is a convenience function that simply sends and then recvs\&. \fBParameters
\fIms_timeout\fP max time to wait for a response
.RE
.PP
\fBNote:\fP
.RS 4
the iov[0] must include a \fBqb_ipc_request_header\fP at the top of the message\&. The server will read the size field to determine how much to recv\&.
.PP
that msg_ptr will include a \fBqb_ipc_response_header\fP at the top of the message\&.
.RE
.PP
\fBSee also:\fP
.RS 4
\fBqb_ipcc_sendv()\fP \fBqb_ipcc_recv()\fP

View File

@ -1,4 +1,4 @@
.TH "qbipcs.h" 3 "Sun Mar 11 2012" "Version 0.11.1" "libqb" \" -*- nroff -*-
.TH "qbipcs.h" 3 "Mon Sep 10 2012" "Version 0.14.2" "libqb" \" -*- nroff -*-
.ad l
.nh
.SH NAME
@ -30,6 +30,9 @@ Server IPC API\&.
.RI "struct \fBqb_ipcs_connection_stats\fP"
.br
.ti -1c
.RI "struct \fBqb_ipcs_connection_stats_2\fP"
.br
.ti -1c
.RI "struct \fBqb_ipcs_poll_handlers\fP"
.br
.ti -1c
@ -164,6 +167,10 @@ Server IPC API\&.
.br
.RI "\fIGet the connection statistics\&. \fP"
.ti -1c
.RI "struct \fBqb_ipcs_connection_stats_2\fP * \fBqb_ipcs_connection_stats_get_2\fP (\fBqb_ipcs_connection_t\fP *c, int32_t clear_after_read)"
.br
.RI "\fIGet (and allocate) the connection statistics\&. \fP"
.ti -1c
.RI "int32_t \fBqb_ipcs_stats_get\fP (\fBqb_ipcs_service_t\fP *pt, struct \fBqb_ipcs_stats\fP *stats, int32_t clear_after_read)"
.br
.RI "\fIGet the service statistics\&. \fP"
@ -175,6 +182,10 @@ Server IPC API\&.
.RI "\fBqb_ipcs_connection_t\fP * \fBqb_ipcs_connection_next_get\fP (\fBqb_ipcs_service_t\fP *pt, \fBqb_ipcs_connection_t\fP *current)"
.br
.RI "\fIGet the next connection\&. \fP"
.ti -1c
.RI "void \fBqb_ipcs_connection_auth_set\fP (\fBqb_ipcs_connection_t\fP *conn, uid_t uid, gid_t gid, mode_t mode)"
.br
.RI "\fISet the permissions on and shared memory files so that both processes can read and write to them\&. \fP"
.in -1c
.SH "Detailed Description"
.PP
@ -183,18 +194,23 @@ Server IPC API\&.
.SH "Typedef Documentation"
.PP
.SS "typedef int32_t(* \fBqb_ipcs_connection_accept_fn\fP)(\fBqb_ipcs_connection_t\fP *c, uid_t uid, gid_t gid)"
.SS "typedef int32_t(* qb_ipcs_connection_accept_fn)(\fBqb_ipcs_connection_t\fP *c, uid_t uid, gid_t gid)"
.PP
This callback is to check wether you want to accept a new connection\&. The type of checks you should do are authentication, service availabilty or process resource constraints\&.
.PP
\fBReturns:\fP
.RS 4
0 to accept or -errno to indicate a failure (sent back to the client)
0 to accept or -errno to indicate a failure (sent back to the client)
.RE
.PP
\fBNote:\fP
.RS 4
you can call \fBqb_ipcs_connection_auth_set()\fP within this function\&.
.RE
.PP
.SS "typedef int32_t(* \fBqb_ipcs_connection_closed_fn\fP)(\fBqb_ipcs_connection_t\fP *c)"
.SS "typedef int32_t(* qb_ipcs_connection_closed_fn)(\fBqb_ipcs_connection_t\fP *c)"
.PP
This is called after a connection has been disconnected\&. \fBNote:\fP
@ -203,27 +219,27 @@ if you return anything but 0 this function will be repeativily called (until 0 i
.RE
.PP
.SS "typedef void(* \fBqb_ipcs_connection_created_fn\fP)(\fBqb_ipcs_connection_t\fP *c)"
.SS "typedef void(* qb_ipcs_connection_created_fn)(\fBqb_ipcs_connection_t\fP *c)"
.PP
This is called after a new connection has been created\&.
.SS "typedef void(* \fBqb_ipcs_connection_destroyed_fn\fP)(\fBqb_ipcs_connection_t\fP *c)"
.SS "typedef void(* qb_ipcs_connection_destroyed_fn)(\fBqb_ipcs_connection_t\fP *c)"
.PP
This is called just before a connection is freed\&.
.SS "typedef struct qb_ipcs_connection \fBqb_ipcs_connection_t\fP"
.SS "typedef int32_t(* \fBqb_ipcs_dispatch_add_fn\fP)(enum \fBqb_loop_priority\fP p, int32_t fd, int32_t events, void *data, \fBqb_ipcs_dispatch_fn_t\fP fn)"
.SS "typedef int32_t(* qb_ipcs_dispatch_add_fn)(enum \fBqb_loop_priority\fP p, int32_t fd, int32_t events, void *data, \fBqb_ipcs_dispatch_fn_t\fP fn)"
.SS "typedef int32_t(* \fBqb_ipcs_dispatch_del_fn\fP)(int32_t fd)"
.SS "typedef int32_t(* qb_ipcs_dispatch_del_fn)(int32_t fd)"
.SS "typedef int32_t(* \fBqb_ipcs_dispatch_fn_t\fP)(int32_t fd, int32_t revents, void *data)"
.SS "typedef int32_t(* qb_ipcs_dispatch_fn_t)(int32_t fd, int32_t revents, void *data)"
.SS "typedef int32_t(* \fBqb_ipcs_dispatch_mod_fn\fP)(enum \fBqb_loop_priority\fP p, int32_t fd, int32_t events, void *data, \fBqb_ipcs_dispatch_fn_t\fP fn)"
.SS "typedef int32_t(* qb_ipcs_dispatch_mod_fn)(enum \fBqb_loop_priority\fP p, int32_t fd, int32_t events, void *data, \fBqb_ipcs_dispatch_fn_t\fP fn)"
.SS "typedef int32_t(* \fBqb_ipcs_job_add_fn\fP)(enum \fBqb_loop_priority\fP p, void *data, \fBqb_loop_job_dispatch_fn\fP dispatch_fn)"
.SS "typedef int32_t(* qb_ipcs_job_add_fn)(enum \fBqb_loop_priority\fP p, void *data, \fBqb_loop_job_dispatch_fn\fP dispatch_fn)"
.SS "typedef int32_t(* \fBqb_ipcs_msg_process_fn\fP)(\fBqb_ipcs_connection_t\fP *c, void *data, size_t size)"
.SS "typedef int32_t(* qb_ipcs_msg_process_fn)(\fBqb_ipcs_connection_t\fP *c, void *data, size_t size)"
.PP
This is the message processing calback\&. It is called with the message data\&.
@ -249,7 +265,32 @@ This is the message processing calback\&. It is called with the message data\&.
.SH "Function Documentation"
.PP
.SS "\fBqb_ipcs_connection_t\fP* \fBqb_ipcs_connection_first_get\fP (\fBqb_ipcs_service_t\fP *pt)"
.SS "void qb_ipcs_connection_auth_set (\fBqb_ipcs_connection_t\fP *conn, uid_tuid, gid_tgid, mode_tmode)"
.PP
Set the permissions on and shared memory files so that both processes can read and write to them\&. \fBParameters:\fP
.RS 4
\fIconn\fP connection instance
.br
\fIuid\fP the user id to set\&.
.br
\fIgid\fP the group id to set\&.
.br
\fImode\fP the mode to set\&.
.RE
.PP
\fBSee also:\fP
.RS 4
chmod() chown()
.RE
.PP
\fBNote:\fP
.RS 4
this must be called within the \fBqb_ipcs_connection_accept_fn()\fP callback\&.
.RE
.PP
.SS "\fBqb_ipcs_connection_t\fP* qb_ipcs_connection_first_get (\fBqb_ipcs_service_t\fP *pt)"
.PP
Get the first connection\&. \fBNote:\fP
@ -268,7 +309,7 @@ first connection
.RE
.PP
.SS "\fBqb_ipcs_connection_t\fP* \fBqb_ipcs_connection_next_get\fP (\fBqb_ipcs_service_t\fP *pt, \fBqb_ipcs_connection_t\fP *current)"
.SS "\fBqb_ipcs_connection_t\fP* qb_ipcs_connection_next_get (\fBqb_ipcs_service_t\fP *pt, \fBqb_ipcs_connection_t\fP *current)"
.PP
Get the next connection\&. \fBNote:\fP
@ -289,7 +330,7 @@ next connection
.RE
.PP
.SS "void \fBqb_ipcs_connection_ref\fP (\fBqb_ipcs_connection_t\fP *c)"
.SS "void qb_ipcs_connection_ref (\fBqb_ipcs_connection_t\fP *c)"
.PP
Increment the connection's reference counter\&. \fBParameters:\fP
@ -298,10 +339,15 @@ Increment the connection's reference counter\&. \fBParameters:\fP
.RE
.PP
.SS "int32_t \fBqb_ipcs_connection_stats_get\fP (\fBqb_ipcs_connection_t\fP *c, struct \fBqb_ipcs_connection_stats\fP *stats, int32_tclear_after_read)"
.SS "int32_t qb_ipcs_connection_stats_get (\fBqb_ipcs_connection_t\fP *c, struct \fBqb_ipcs_connection_stats\fP *stats, int32_tclear_after_read)"
.PP
Get the connection statistics\&. \fBParameters:\fP
Get the connection statistics\&. \fBDeprecated\fP
.RS 4
from v0\&.13\&.0 onwards, use qb_ipcs_connection_stats_get_2
.RE
.PP
\fBParameters:\fP
.RS 4
\fIstats\fP (out) the statistics structure
.br
@ -316,7 +362,25 @@ Get the connection statistics\&. \fBParameters:\fP
.RE
.PP
.SS "void \fBqb_ipcs_connection_unref\fP (\fBqb_ipcs_connection_t\fP *c)"
.SS "struct \fBqb_ipcs_connection_stats_2\fP* qb_ipcs_connection_stats_get_2 (\fBqb_ipcs_connection_t\fP *c, int32_tclear_after_read)\fC [read]\fP"
.PP
Get (and allocate) the connection statistics\&. \fBParameters:\fP
.RS 4
\fIclear_after_read\fP clear stats after copying them into stats
.br
\fIc\fP connection instance
.RE
.PP
\fBReturn values:\fP
.RS 4
\fINULL\fP if no memory or invalid connection
.br
\fIallocated\fP statistics structure (user must free it)\&.
.RE
.PP
.SS "void qb_ipcs_connection_unref (\fBqb_ipcs_connection_t\fP *c)"
.PP
Decrement the connection's reference counter\&. \fBParameters:\fP
@ -325,7 +389,7 @@ Decrement the connection's reference counter\&. \fBParameters:\fP
.RE
.PP
.SS "void* \fBqb_ipcs_context_get\fP (\fBqb_ipcs_connection_t\fP *c)"
.SS "void* qb_ipcs_context_get (\fBqb_ipcs_connection_t\fP *c)"
.PP
Get the context (set previously) \fBParameters:\fP
@ -344,7 +408,7 @@ the context
.RE
.PP
.SS "void \fBqb_ipcs_context_set\fP (\fBqb_ipcs_connection_t\fP *c, void *context)"
.SS "void qb_ipcs_context_set (\fBqb_ipcs_connection_t\fP *c, void *context)"
.PP
Associate a 'user' pointer with this connection\&. \fBParameters:\fP
@ -360,7 +424,7 @@ Associate a 'user' pointer with this connection\&. \fBParameters:\fP
.RE
.PP
.SS "\fBqb_ipcs_service_t\fP* \fBqb_ipcs_create\fP (const char *name, int32_tservice_id, enum \fBqb_ipc_type\fPtype, struct \fBqb_ipcs_service_handlers\fP *handlers)"
.SS "\fBqb_ipcs_service_t\fP* qb_ipcs_create (const char *name, int32_tservice_id, enum \fBqb_ipc_type\fPtype, struct \fBqb_ipcs_service_handlers\fP *handlers)"
.PP
Create a new IPC server\&. \fBParameters:\fP
@ -380,7 +444,7 @@ the new service instance\&.
.RE
.PP
.SS "void \fBqb_ipcs_destroy\fP (\fBqb_ipcs_service_t\fP *s)"
.SS "void qb_ipcs_destroy (\fBqb_ipcs_service_t\fP *s)"
.PP
Destroy the IPC server\&. \fBParameters:\fP
@ -389,7 +453,7 @@ Destroy the IPC server\&. \fBParameters:\fP
.RE
.PP
.SS "void \fBqb_ipcs_disconnect\fP (\fBqb_ipcs_connection_t\fP *c)"
.SS "void qb_ipcs_disconnect (\fBqb_ipcs_connection_t\fP *c)"
.PP
Disconnect from this client\&. \fBParameters:\fP
@ -398,7 +462,7 @@ Disconnect from this client\&. \fBParameters:\fP
.RE
.PP
.SS "ssize_t \fBqb_ipcs_event_send\fP (\fBqb_ipcs_connection_t\fP *c, const void *data, size_tsize)"
.SS "ssize_t qb_ipcs_event_send (\fBqb_ipcs_connection_t\fP *c, const void *data, size_tsize)"
.PP
Send an asyncronous event message to the client\&. \fBParameters:\fP
@ -412,11 +476,16 @@ Send an asyncronous event message to the client\&. \fBParameters:\fP
.PP
\fBReturns:\fP
.RS 4
size sent or -errno for errors
size sent or -errno for errors
.RE
.PP
\fBNote:\fP
.RS 4
the data must include a \fBqb_ipc_response_header\fP at the top of the message\&. The client will read the size field to determine how much to recv\&.
.RE
.PP
.SS "ssize_t \fBqb_ipcs_event_sendv\fP (\fBqb_ipcs_connection_t\fP *c, const struct iovec *iov, size_tiov_len)"
.SS "ssize_t qb_ipcs_event_sendv (\fBqb_ipcs_connection_t\fP *c, const struct iovec *iov, size_tiov_len)"
.PP
Send an asyncronous event message to the client\&. \fBParameters:\fP
@ -430,11 +499,16 @@ Send an asyncronous event message to the client\&. \fBParameters:\fP
.PP
\fBReturns:\fP
.RS 4
size sent or -errno for errors
size sent or -errno for errors
.RE
.PP
\fBNote:\fP
.RS 4
the iov[0] must be a \fBqb_ipc_response_header\fP\&. The client will read the size field to determine how much to recv\&.
.RE
.PP
.SS "void \fBqb_ipcs_poll_handlers_set\fP (\fBqb_ipcs_service_t\fP *s, struct \fBqb_ipcs_poll_handlers\fP *handlers)"
.SS "void qb_ipcs_poll_handlers_set (\fBqb_ipcs_service_t\fP *s, struct \fBqb_ipcs_poll_handlers\fP *handlers)"
.PP
Set your poll callbacks\&. \fBParameters:\fP
@ -445,7 +519,7 @@ Set your poll callbacks\&. \fBParameters:\fP
.RE
.PP
.SS "void \fBqb_ipcs_ref\fP (\fBqb_ipcs_service_t\fP *s)"
.SS "void qb_ipcs_ref (\fBqb_ipcs_service_t\fP *s)"
.PP
Increase the reference counter on the service object\&. \fBParameters:\fP
@ -454,7 +528,7 @@ Increase the reference counter on the service object\&. \fBParameters:\fP
.RE
.PP
.SS "void \fBqb_ipcs_request_rate_limit\fP (\fBqb_ipcs_service_t\fP *s, enum \fBqb_ipcs_rate_limit\fPrl)"
.SS "void qb_ipcs_request_rate_limit (\fBqb_ipcs_service_t\fP *s, enum \fBqb_ipcs_rate_limit\fPrl)"
.PP
Limit the incomming request rate\&. \fBParameters:\fP
@ -465,7 +539,7 @@ Limit the incomming request rate\&. \fBParameters:\fP
.RE
.PP
.SS "ssize_t \fBqb_ipcs_response_send\fP (\fBqb_ipcs_connection_t\fP *c, const void *data, size_tsize)"
.SS "ssize_t qb_ipcs_response_send (\fBqb_ipcs_connection_t\fP *c, const void *data, size_tsize)"
.PP
Send a response to a incomming request\&. \fBParameters:\fP
@ -479,11 +553,16 @@ Send a response to a incomming request\&. \fBParameters:\fP
.PP
\fBReturns:\fP
.RS 4
size sent or -errno for errors
size sent or -errno for errors
.RE
.PP
\fBNote:\fP
.RS 4
the data must include a \fBqb_ipc_response_header\fP at the top of the message\&. The client will read the size field to determine how much to recv\&.
.RE
.PP
.SS "ssize_t \fBqb_ipcs_response_sendv\fP (\fBqb_ipcs_connection_t\fP *c, const struct iovec *iov, size_tiov_len)"
.SS "ssize_t qb_ipcs_response_sendv (\fBqb_ipcs_connection_t\fP *c, const struct iovec *iov, size_tiov_len)"
.PP
Send a response to a incomming request\&. \fBParameters:\fP
@ -497,11 +576,16 @@ Send a response to a incomming request\&. \fBParameters:\fP
.PP
\fBReturns:\fP
.RS 4
size sent or -errno for errors
size sent or -errno for errors
.RE
.PP
\fBNote:\fP
.RS 4
the iov[0] must be a \fBqb_ipc_response_header\fP\&. The client will read the size field to determine how much to recv\&.
.RE
.PP
.SS "int32_t \fBqb_ipcs_run\fP (\fBqb_ipcs_service_t\fP *s)"
.SS "int32_t qb_ipcs_run (\fBqb_ipcs_service_t\fP *s)"
.PP
run the new IPC server\&. \fBParameters:\fP
@ -515,7 +599,7 @@ run the new IPC server\&. \fBParameters:\fP
.RE
.PP
.SS "int32_t \fBqb_ipcs_service_id_get\fP (\fBqb_ipcs_connection_t\fP *c)"
.SS "int32_t qb_ipcs_service_id_get (\fBqb_ipcs_connection_t\fP *c)"
.PP
Get the service id related to this connection's service\&. (as passed into \fBqb_ipcs_create()\fP
@ -526,7 +610,7 @@ service id\&.
.RE
.PP
.SS "int32_t \fBqb_ipcs_stats_get\fP (\fBqb_ipcs_service_t\fP *pt, struct \fBqb_ipcs_stats\fP *stats, int32_tclear_after_read)"
.SS "int32_t qb_ipcs_stats_get (\fBqb_ipcs_service_t\fP *pt, struct \fBqb_ipcs_stats\fP *stats, int32_tclear_after_read)"
.PP
Get the service statistics\&. \fBParameters:\fP
@ -544,7 +628,7 @@ Get the service statistics\&. \fBParameters:\fP
.RE
.PP
.SS "void \fBqb_ipcs_unref\fP (\fBqb_ipcs_service_t\fP *s)"
.SS "void qb_ipcs_unref (\fBqb_ipcs_service_t\fP *s)"
.PP
Decrease the reference counter on the service object\&. \fBParameters:\fP

View File

@ -1,4 +1,4 @@
.TH "qblist.h" 3 "Sun Mar 11 2012" "Version 0.11.1" "libqb" \" -*- nroff -*-
.TH "qblist.h" 3 "Mon Sep 10 2012" "Version 0.14.2" "libqb" \" -*- nroff -*-
.ad l
.nh
.SH NAME
@ -21,7 +21,7 @@ This is a kernel style list implementation\&.
.RI "struct \fBqb_list_head\fP"
.br
.in -1c
.SS "Defines"
.SS "Macros"
.in +1c
.ti -1c
@ -106,9 +106,9 @@ Steven Dake sdake@redhat.com
.RE
.PP
.SH "Define Documentation"
.SH "Macro Definition Documentation"
.PP
.SS "#define \fBQB_INIT_LIST_HEAD\fP(ptr)"
.SS "#define QB_INIT_LIST_HEAD(ptr)"
\fBValue:\fP
.PP
.nf
@ -116,11 +116,11 @@ do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
.fi
.SS "#define \fBQB_LIST_DECLARE\fP(name) struct \fBqb_list_head\fP name = { &(name), &(name) }"
.SS "#define QB_LIST_DECLARE(name) struct \fBqb_list_head\fP name = { &(name), &(name) }"
.PP
Declare and initialize a list head\&.
.SS "#define \fBqb_list_entry\fP(ptr, type, member) ((type *)((char *)(ptr)-(char*)(&((type *)0)->member)))"
.SS "#define qb_list_entry(ptr, type, member) ((type *)((char *)(ptr)-(char*)(&((type *)0)->member)))"
.PP
Get the struct for this entry\&. \fBParameters:\fP
@ -133,7 +133,7 @@ Get the struct for this entry\&. \fBParameters:\fP
.RE
.PP
.SS "#define \fBqb_list_for_each\fP(pos, head) for (pos = (head)->next; pos != (head); pos = pos->next)"
.SS "#define qb_list_for_each(pos, head) for (pos = (head)->next; pos != (head); pos = pos->next)"
.PP
Iterate over a list\&. \fBParameters:\fP
@ -146,7 +146,7 @@ Iterate over a list\&. \fBParameters:\fP
.PP
Referenced by qb_list_length()\&.
.SS "#define \fBqb_list_for_each_entry\fP(pos, head, member)"
.SS "#define qb_list_for_each_entry(pos, head, member)"
\fBValue:\fP
.PP
.nf
@ -165,7 +165,7 @@ Iterate over list of given type\&. \fBParameters:\fP
.RE
.PP
.SS "#define \fBqb_list_for_each_entry_reverse\fP(pos, head, member)"
.SS "#define qb_list_for_each_entry_reverse(pos, head, member)"
\fBValue:\fP
.PP
.nf
@ -184,7 +184,7 @@ Iterate backwards over list of given type\&. \fBParameters:\fP
.RE
.PP
.SS "#define \fBqb_list_for_each_entry_safe\fP(pos, n, head, member)"
.SS "#define qb_list_for_each_entry_safe(pos, n, head, member)"
\fBValue:\fP
.PP
.nf
@ -206,7 +206,7 @@ Iterate over list of given type safe against removal of list entry\&. \fBParamet
.RE
.PP
.SS "#define \fBqb_list_for_each_entry_safe_reverse\fP(pos, n, head, member)"
.SS "#define qb_list_for_each_entry_safe_reverse(pos, n, head, member)"
\fBValue:\fP
.PP
.nf
@ -228,7 +228,7 @@ Iterate backwards over list safe against removal\&. \fBParameters:\fP
.RE
.PP
.SS "#define \fBqb_list_for_each_reverse\fP(pos, head) for (pos = (head)->prev; pos != (head); pos = pos->prev)"
.SS "#define qb_list_for_each_reverse(pos, head) for (pos = (head)->prev; pos != (head); pos = pos->prev)"
.PP
Iterate over a list backwards\&. \fBParameters:\fP
@ -239,7 +239,7 @@ Iterate over a list backwards\&. \fBParameters:\fP
.RE
.PP
.SS "#define \fBqb_list_for_each_safe\fP(pos, n, head)"
.SS "#define qb_list_for_each_safe(pos, n, head)"
\fBValue:\fP
.PP
.nf
@ -259,7 +259,7 @@ Iterate over a list safe against removal of list entry\&. \fBParameters:\fP
.SH "Function Documentation"
.PP
.SS "static void \fBqb_list_add\fP (struct \fBqb_list_head\fP *element, struct \fBqb_list_head\fP *head)\fC [inline, static]\fP"
.SS "static void qb_list_add (struct \fBqb_list_head\fP *element, struct \fBqb_list_head\fP *head)\fC [inline]\fP, \fC [static]\fP"
.PP
Add this element to the list\&. \fBParameters:\fP
@ -272,7 +272,7 @@ Add this element to the list\&. \fBParameters:\fP
.PP
References qb_list_head::next, and qb_list_head::prev\&.
.SS "static void \fBqb_list_add_tail\fP (struct \fBqb_list_head\fP *element, struct \fBqb_list_head\fP *head)\fC [inline, static]\fP"
.SS "static void qb_list_add_tail (struct \fBqb_list_head\fP *element, struct \fBqb_list_head\fP *head)\fC [inline]\fP, \fC [static]\fP"
.PP
Add to the list (but at the end of the list)\&. \fBParameters:\fP
@ -290,7 +290,7 @@ Add to the list (but at the end of the list)\&. \fBParameters:\fP
.PP
References qb_list_head::next, and qb_list_head::prev\&.
.SS "static void \fBqb_list_del\fP (struct \fBqb_list_head\fP *_remove)\fC [inline, static]\fP"
.SS "static void qb_list_del (struct \fBqb_list_head\fP *_remove)\fC [inline]\fP, \fC [static]\fP"
.PP
Delete an entry from the list\&. \fBParameters:\fP
@ -301,7 +301,7 @@ Delete an entry from the list\&. \fBParameters:\fP
.PP
References qb_list_head::next, and qb_list_head::prev\&.
.SS "static int32_t \fBqb_list_empty\fP (const struct \fBqb_list_head\fP *head)\fC [inline, static]\fP"
.SS "static int32_t qb_list_empty (const struct \fBqb_list_head\fP *head)\fC [inline]\fP, \fC [static]\fP"
.PP
A quick test to see if the list is empty (pointing to it's self)\&. \fBParameters:\fP
@ -317,7 +317,7 @@ boolean true/false
.PP
References qb_list_head::next\&.
.SS "static void \fBqb_list_init\fP (struct \fBqb_list_head\fP *head)\fC [inline, static]\fP"
.SS "static void qb_list_init (struct \fBqb_list_head\fP *head)\fC [inline]\fP, \fC [static]\fP"
.PP
Initialize the list entry\&. Points next and prev pointers to head\&.
@ -330,7 +330,7 @@ Initialize the list entry\&. Points next and prev pointers to head\&.
.PP
References qb_list_head::next, and qb_list_head::prev\&.
.SS "static int32_t \fBqb_list_length\fP (struct \fBqb_list_head\fP *head)\fC [inline, static]\fP"
.SS "static int32_t qb_list_length (struct \fBqb_list_head\fP *head)\fC [inline]\fP, \fC [static]\fP"
.PP
Count the number of items in the list\&. \fBParameters:\fP
@ -346,7 +346,7 @@ length of the list\&.
.PP
References qb_list_for_each\&.
.SS "static void \fBqb_list_splice\fP (struct \fBqb_list_head\fP *list, struct \fBqb_list_head\fP *head)\fC [inline, static]\fP"
.SS "static void qb_list_splice (struct \fBqb_list_head\fP *list, struct \fBqb_list_head\fP *head)\fC [inline]\fP, \fC [static]\fP"
.PP
Join two lists\&. \fBParameters:\fP

View File

@ -1,4 +1,4 @@
.TH "qblog.h" 3 "Sun Mar 11 2012" "Version 0.11.1" "libqb" \" -*- nroff -*-
.TH "qblog.h" 3 "Mon Sep 10 2012" "Version 0.14.2" "libqb" \" -*- nroff -*-
.ad l
.nh
.SH NAME
@ -36,7 +36,7 @@ The logging API provides four main parts (basics, filtering, threading & blackbo
.br
.RI "\fIAn instance of this structure is created in a special ELF section at every dynamic debug callsite\&. \fP"
.in -1c
.SS "Defines"
.SS "Macros"
.in +1c
.ti -1c
@ -120,7 +120,7 @@ The logging API provides four main parts (basics, filtering, threading & blackbo
.RI "enum \fBqb_log_target_state\fP { \fBQB_LOG_STATE_UNUSED\fP = 1, \fBQB_LOG_STATE_DISABLED\fP = 2, \fBQB_LOG_STATE_ENABLED\fP = 3 }"
.br
.ti -1c
.RI "enum \fBqb_log_conf\fP { \fBQB_LOG_CONF_ENABLED\fP, \fBQB_LOG_CONF_FACILITY\fP, \fBQB_LOG_CONF_DEBUG\fP, \fBQB_LOG_CONF_SIZE\fP, \fBQB_LOG_CONF_THREADED\fP, \fBQB_LOG_CONF_PRIORITY_BUMP\fP, \fBQB_LOG_CONF_STATE_GET\fP }"
.RI "enum \fBqb_log_conf\fP { \fBQB_LOG_CONF_ENABLED\fP, \fBQB_LOG_CONF_FACILITY\fP, \fBQB_LOG_CONF_DEBUG\fP, \fBQB_LOG_CONF_SIZE\fP, \fBQB_LOG_CONF_THREADED\fP, \fBQB_LOG_CONF_PRIORITY_BUMP\fP, \fBQB_LOG_CONF_STATE_GET\fP, \fBQB_LOG_CONF_FILE_SYNC\fP }"
.br
.ti -1c
.RI "enum \fBqb_log_filter_type\fP { \fBQB_LOG_FILTER_FILE\fP, \fBQB_LOG_FILTER_FUNCTION\fP, \fBQB_LOG_FILTER_FORMAT\fP }"
@ -294,13 +294,13 @@ Call \fBqb_log()\fP to generate a log message\&. Then to write the message somew
Simplist possible use:
.PP
.nf
main() {
main() {
qb_log_init('simple-log', LOG_DAEMON, LOG_INFO);
// \&.\&.\&.
qb_log(LOG_WARNING, 'watch out');
// \&.\&.\&.
qb_log_fini();
}
}
.fi
.PP
@ -349,6 +349,14 @@ To workaround your syslog daemon filtering all messages > LOG_INFO
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_PRIORITY_BUMP,
LOG_INFO - LOG_DEBUG);
.fi
.PP
.PP
To ensure all logs to file targets are fsync'ed (default QB_FALSE)
.PP
.nf
qb_log_ctl(mytarget, QB_LOG_CONF_FILE_SYNC, QB_TRUE);
.fi
.PP
.PP
@ -399,7 +407,7 @@ To achieve non-blocking logging you can use threaded logging\&. So any calls to
Threaded logging use:
.PP
.nf
main() {
main() {
qb_log_init('simple-log', LOG_DAEMON, LOG_INFO);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_THREADED, QB_TRUE);
// \&.\&.\&.
@ -410,7 +418,7 @@ Threaded logging use:
qb_log(LOG_WARNING, 'watch out');
// \&.\&.\&.
qb_log_fini();
}
}
.fi
.PP
@ -428,18 +436,18 @@ the blackbox is not enabled by default\&.
Blackbox usage:
.PP
.nf
static void sigsegv_handler(int sig)
{
static void sigsegv_handler(int sig)
{
(void)signal (SIGSEGV, SIG_DFL);
qb_log_blackbox_write_to_file('simple-log\&.fdata');
qb_log_fini();
raise(SIGSEGV);
}
main() {
}
main() {
signal(SIGSEGV, sigsegv_handler);
qb_log_init('simple-log', LOG_DAEMON, LOG_INFO);
qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, '*', LOG_DEBUG);
@ -449,7 +457,7 @@ Blackbox usage:
qb_log(LOG_WARNING, 'watch out');
// \&.\&.\&.
qb_log_fini();
}
}
.fi
.PP
@ -461,7 +469,7 @@ You can tag messages using the second argument to \fBqb_logt()\fP or by using \f
.PP
.PP
.nf
const char* my_tags_stringify(uint32_t tags) {
const char* my_tags_stringify(uint32_t tags) {
if (qb_bit_is_set(tags, QB_LOG_TAG_LIBQB_MSG_BIT) {
return 'libqb';
} else if (tags == 3) {
@ -469,36 +477,36 @@ You can tag messages using the second argument to \fBqb_logt()\fP or by using \f
} else {
return 'MAIN';
}
}
main() {
}
main() {
// \&.\&.\&.
qb_log_tags_stringify_fn_set(my_tags_stringify);
qb_log_format_set(QB_LOG_STDERR, '[%5g] %p %b');
// \&.\&.\&.
qb_logt(LOG_INFO, 3, 'hello');
qb_logt(LOG_INFO, 0, 'hello');
}
}
.fi
.PP
The code above will produce:
.PP
.nf
[libqb] some message
[three] info hello
[MAIN ] info hello
[libqb] some message
[three] info hello
[MAIN ] info hello
.fi
.PP
.SH "Define Documentation"
.SH "Macro Definition Documentation"
.PP
.SS "#define \fBLOG_TRACE\fP (LOG_DEBUG + 1)"
.SS "#define LOG_TRACE (LOG_DEBUG + 1)"
.SS "#define \fBqb_enter\fP() \fBqb_log\fP(\fBLOG_TRACE\fP, 'ENTERING %s()', __func__)"
.SS "#define qb_enter() \fBqb_log\fP(\fBLOG_TRACE\fP, 'ENTERING %s()', __func__)"
.SS "#define \fBqb_leave\fP() \fBqb_log\fP(\fBLOG_TRACE\fP, 'LEAVING %s()', __func__)"
.SS "#define qb_leave() \fBqb_log\fP(\fBLOG_TRACE\fP, 'LEAVING %s()', __func__)"
.SS "#define \fBqb_log\fP(\fBpriority\fP, fmt, args\&.\&.\&.) \fBqb_logt\fP(\fBpriority\fP, 0, fmt, ##args)"
.SS "#define qb_log(\fBpriority\fP, fmt, args\&.\&.\&.) \fBqb_logt\fP(\fBpriority\fP, 0, fmt, ##args)"
.PP
This is the main function to generate a log message\&. \fBParameters:\fP
@ -511,9 +519,9 @@ This is the main function to generate a log message\&. \fBParameters:\fP
.RE
.PP
.SS "#define \fBQB_LOG_BLACKBOX\fP 2"
.SS "#define QB_LOG_BLACKBOX 2"
.SS "#define \fBQB_LOG_INIT_DATA\fP(name)"
.SS "#define QB_LOG_INIT_DATA(name)"
\fBValue:\fP
.PP
.nf
@ -521,23 +529,23 @@ void name(void); \
void name(void) { if (__start___verbose != __stop___verbose) {assert(1);} } \
void __attribute__ ((constructor)) name(void);
.fi
.SS "#define \fBQB_LOG_MAX_LEN\fP 512"
.SS "#define QB_LOG_MAX_LEN 512"
.SS "#define \fBQB_LOG_STDERR\fP 1"
.SS "#define QB_LOG_STDERR 1"
.SS "#define \fBQB_LOG_STDOUT\fP 3"
.SS "#define QB_LOG_STDOUT 3"
.SS "#define \fBQB_LOG_STRERROR_MAX_LEN\fP 128"
.SS "#define QB_LOG_STRERROR_MAX_LEN 128"
.SS "#define \fBQB_LOG_SYSLOG\fP 0"
.SS "#define QB_LOG_SYSLOG 0"
.SS "#define \fBQB_LOG_TAG_LIBQB_MSG\fP (1 << \fBQB_LOG_TAG_LIBQB_MSG_BIT\fP)"
.SS "#define QB_LOG_TAG_LIBQB_MSG (1 << \fBQB_LOG_TAG_LIBQB_MSG_BIT\fP)"
.SS "#define \fBQB_LOG_TAG_LIBQB_MSG_BIT\fP 31"
.SS "#define QB_LOG_TAG_LIBQB_MSG_BIT 31"
.SS "#define \fBQB_LOG_TARGET_MAX\fP 32"
.SS "#define QB_LOG_TARGET_MAX 32"
.SS "#define \fBqb_logt\fP(\fBpriority\fP, \fBtags\fP, fmt, args\&.\&.\&.)"
.SS "#define qb_logt(\fBpriority\fP, \fBtags\fP, fmt, args\&.\&.\&.)"
\fBValue:\fP
.PP
.nf
@ -561,7 +569,7 @@ This is the function to generate a log message if you want to manually add tags\
.RE
.PP
.SS "#define \fBqb_perror\fP(\fBpriority\fP, fmt, args\&.\&.\&.)"
.SS "#define qb_perror(\fBpriority\fP, fmt, args\&.\&.\&.)"
\fBValue:\fP
.PP
.nf
@ -584,17 +592,17 @@ This is similar to perror except it goes into the logging system\&. \fBParameter
.SH "Typedef Documentation"
.PP
.SS "typedef void(* \fBqb_log_close_fn\fP)(int32_t t)"
.SS "typedef void(* qb_log_close_fn)(int32_t t)"
.SS "typedef void(* \fBqb_log_filter_fn\fP)(struct \fBqb_log_callsite\fP *cs)"
.SS "typedef void(* qb_log_filter_fn)(struct \fBqb_log_callsite\fP *cs)"
.SS "typedef void(* \fBqb_log_logger_fn\fP)(int32_t t, struct \fBqb_log_callsite\fP *cs, time_t timestamp, const char *msg)"
.SS "typedef void(* qb_log_logger_fn)(int32_t t, struct \fBqb_log_callsite\fP *cs, time_t timestamp, const char *msg)"
.SS "typedef void(* \fBqb_log_reload_fn\fP)(int32_t t)"
.SS "typedef void(* qb_log_reload_fn)(int32_t t)"
.SS "typedef const char*(* \fBqb_log_tags_stringify_fn\fP)(uint32_t \fBtags\fP)"
.SS "typedef const char*(* qb_log_tags_stringify_fn)(uint32_t \fBtags\fP)"
.SS "typedef void(* \fBqb_log_vlogger_fn\fP)(int32_t t, struct \fBqb_log_callsite\fP *cs, time_t timestamp, va_list ap)"
.SS "typedef void(* qb_log_vlogger_fn)(int32_t t, struct \fBqb_log_callsite\fP *cs, time_t timestamp, va_list ap)"
.SH "Enumeration Type Documentation"
.PP
@ -617,6 +625,8 @@ This is similar to perror except it goes into the logging system\&. \fBParameter
\fB\fIQB_LOG_CONF_PRIORITY_BUMP \fP\fP
.TP
\fB\fIQB_LOG_CONF_STATE_GET \fP\fP
.TP
\fB\fIQB_LOG_CONF_FILE_SYNC \fP\fP
.SS "enum \fBqb_log_filter_conf\fP"
@ -662,17 +672,17 @@ This is similar to perror except it goes into the logging system\&. \fBParameter
.SH "Function Documentation"
.PP
.SS "struct \fBqb_log_callsite\fP \fB__attribute__\fP ((aligned(8)))"
.SS "struct \fBqb_log_callsite\fP __attribute__ ((aligned(8)))"
.SS "void \fBqb_log_blackbox_print_from_file\fP (const char *filename)"
.SS "void qb_log_blackbox_print_from_file (const char *filename)"
.PP
Read the blackbox for file and print it out\&.
.SS "ssize_t \fBqb_log_blackbox_write_to_file\fP (const char *filename)"
.SS "ssize_t qb_log_blackbox_write_to_file (const char *filename)"
.PP
Write the blackbox to file\&.
.SS "struct \fBqb_log_callsite\fP* \fBqb_log_callsite_get\fP (const char *function, const char *filename, const char *format, uint8_tpriority, uint32_tlineno, uint32_ttags)\fC [read]\fP"
.SS "struct \fBqb_log_callsite\fP* qb_log_callsite_get (const char *function, const char *filename, const char *format, uint8_tpriority, uint32_tlineno, uint32_ttags)\fC [read]\fP"
.PP
Get or create a callsite at the give position\&. The result can then be passed into \fBqb_log_real_()\fP
@ -693,11 +703,11 @@ Get or create a callsite at the give position\&. The result can then be passed i
.RE
.PP
.SS "void \fBqb_log_callsites_dump\fP (void)"
.SS "void qb_log_callsites_dump (void)"
.PP
Dump the callsite info to stdout\&.
.SS "int32_t \fBqb_log_callsites_register\fP (struct \fBqb_log_callsite\fP *_start, struct \fBqb_log_callsite\fP *_stop)"
.SS "int32_t qb_log_callsites_register (struct \fBqb_log_callsite\fP *_start, struct \fBqb_log_callsite\fP *_stop)"
.PP
If you are using dynamically loadable modules via dlopen() and you load them after \fBqb_log_init()\fP then after you load the module you will need to do the following to get the filters to work in that module\&. .PP
@ -708,7 +718,7 @@ If you are using dynamically loadable modules via dlopen() and you load them aft
.fi
.PP
.SS "int32_t \fBqb_log_ctl\fP (int32_ttarget, enum \fBqb_log_conf\fPconf_type, int32_targ)"
.SS "int32_t qb_log_ctl (int32_ttarget, enum \fBqb_log_conf\fPconf_type, int32_targ)"
.PP
Main logging control function\&. \fBParameters:\fP
@ -735,11 +745,11 @@ Main logging control function\&. \fBParameters:\fP
.RE
.PP
.SS "void \fBqb_log_custom_close\fP (int32_tt)"
.SS "void qb_log_custom_close (int32_tt)"
.PP
Close a custom log target and release is resources\&.
.SS "int32_t \fBqb_log_custom_open\fP (\fBqb_log_logger_fn\fPlog_fn, \fBqb_log_close_fn\fPclose_fn, \fBqb_log_reload_fn\fPreload_fn, void *user_data)"
.SS "int32_t qb_log_custom_open (\fBqb_log_logger_fn\fPlog_fn, \fBqb_log_close_fn\fPclose_fn, \fBqb_log_reload_fn\fPreload_fn, void *user_data)"
.PP
Open a custom log target\&. \fBReturn values:\fP
@ -750,19 +760,19 @@ Open a custom log target\&. \fBReturn values:\fP
.RE
.PP
.SS "int32_t \fBqb_log_facility2int\fP (const char *fname)"
.SS "int32_t qb_log_facility2int (const char *fname)"
.PP
Convert string 'auth' to equivalent number 'LOG_AUTH' etc\&.
.SS "const char* \fBqb_log_facility2str\fP (int32_tfnum)"
.SS "const char* qb_log_facility2str (int32_tfnum)"
.PP
Convert number 'LOG_AUTH' to equivalent string 'auth' etc\&.
.SS "void \fBqb_log_file_close\fP (int32_tt)"
.SS "void qb_log_file_close (int32_tt)"
.PP
Close a log file and release is resources\&.
.SS "int32_t \fBqb_log_file_open\fP (const char *filename)"
.SS "int32_t qb_log_file_open (const char *filename)"
.PP
Open a log file\&. \fBReturn values:\fP
@ -773,22 +783,22 @@ Open a log file\&. \fBReturn values:\fP
.RE
.PP
.SS "int32_t \fBqb_log_filter_ctl\fP (int32_tvalue, enum \fBqb_log_filter_conf\fPc, enum \fBqb_log_filter_type\fPtype, const char *text, uint8_tlow_priority)"
.SS "int32_t qb_log_filter_ctl (int32_tvalue, enum \fBqb_log_filter_conf\fPc, enum \fBqb_log_filter_type\fPtype, const char *text, uint8_tlow_priority)"
.PP
This allows you modify the 'tags' and 'targets' callsite fields at runtime\&.
.SS "int32_t \fBqb_log_filter_ctl2\fP (int32_tvalue, enum \fBqb_log_filter_conf\fPc, enum \fBqb_log_filter_type\fPtype, const char *text, uint8_thigh_priority, uint8_tlow_priority)"
.SS "int32_t qb_log_filter_ctl2 (int32_tvalue, enum \fBqb_log_filter_conf\fPc, enum \fBqb_log_filter_type\fPtype, const char *text, uint8_thigh_priority, uint8_tlow_priority)"
.PP
This extends \fBqb_log_filter_ctl()\fP by been able to provide a high_priority\&.
.SS "int32_t \fBqb_log_filter_fn_set\fP (\fBqb_log_filter_fn\fPfn)"
.SS "int32_t qb_log_filter_fn_set (\fBqb_log_filter_fn\fPfn)"
.PP
Instead of using the \fBqb_log_filter_ctl()\fP functions you can apply the filters manually by defining a callback and setting the targets field using \fBqb_bit_set()\fP and \fBqb_bit_clear()\fP like the following below\&. .PP
.nf
static void
m_filter(struct qb_log_callsite *cs)
{
static void
m_filter(struct qb_log_callsite *cs)
{
if ((cs->priority >= LOG_ALERT &&
cs->priority <= LOG_DEBUG) &&
strcmp(cs->filename, 'my_c_file\&.c') == 0) {
@ -796,21 +806,21 @@ Instead of using the \fBqb_log_filter_ctl()\fP functions you can apply the filte
} else {
qb_bit_clear(cs->targets, QB_LOG_SYSLOG);
}
}
}
.fi
.PP
.SS "void \fBqb_log_fini\fP (void)"
.SS "void qb_log_fini (void)"
.PP
Logging system finalization function\&. It releases any shared memory\&. Stops the logging thread if running\&. Flushes the last message to their destinations\&.
.SS "void \fBqb_log_format_set\fP (int32_tt, const char *format)"
.SS "void qb_log_format_set (int32_tt, const char *format)"
.PP
Set the format specifiers\&. n FUNCTION NAME f FILENAME l FILELINE p PRIORITY t TIMESTAMP b BUFFER g TAGS N name (passed into qb_log_init) P PID H hostname
.PP
any number between % and character specify field length to pad or chop
.SS "void \fBqb_log_from_external_source\fP (const char *function, const char *filename, const char *format, uint8_tpriority, uint32_tlineno, uint32_ttags, \&.\&.\&.)"
.SS "void qb_log_from_external_source (const char *function, const char *filename, const char *format, uint8_tpriority, uint32_tlineno, uint32_ttags, \&.\&.\&.)"
.PP
This function is to import logs from other code (like libraries) that provide a callback with their logs\&. \fBNote:\fP
@ -834,9 +844,9 @@ the performance of this will not impress you, as the filtering is done on each l
.RE
.PP
.SS "void \fBqb_log_from_external_source_va\fP (const char *function, const char *filename, const char *format, uint8_tpriority, uint32_tlineno, uint32_ttags, va_listap)"
.SS "void qb_log_from_external_source_va (const char *function, const char *filename, const char *format, uint8_tpriority, uint32_tlineno, uint32_ttags, va_listap)"
.SS "void \fBqb_log_init\fP (const char *name, int32_tfacility, uint8_tpriority)"
.SS "void qb_log_init (const char *name, int32_tfacility, uint8_tpriority)"
.PP
Init the logging system\&. \fBParameters:\fP
@ -849,25 +859,25 @@ Init the logging system\&. \fBParameters:\fP
.RE
.PP
.SS "void \fBqb_log_real_\fP (struct \fBqb_log_callsite\fP *cs, \&.\&.\&.)"
.SS "void qb_log_real_ (struct \fBqb_log_callsite\fP *cs, \&.\&.\&.)"
.PP
Internal function: use \fBqb_log()\fP or \fBqb_logt()\fP
.SS "void \fBqb_log_real_va_\fP (struct \fBqb_log_callsite\fP *cs, va_listap)"
.SS "void qb_log_real_va_ (struct \fBqb_log_callsite\fP *cs, va_listap)"
.SS "void \fBqb_log_tags_stringify_fn_set\fP (\fBqb_log_tags_stringify_fn\fPfn)"
.SS "void qb_log_tags_stringify_fn_set (\fBqb_log_tags_stringify_fn\fPfn)"
.PP
Set the callback to map the 'tags' bit map to a string\&.
.SS "void \fBqb_log_target_format\fP (int32_ttarget, struct \fBqb_log_callsite\fP *cs, time_ttimestamp, const char *formatted_message, char *output_buffer)"
.SS "void qb_log_target_format (int32_ttarget, struct \fBqb_log_callsite\fP *cs, time_ttimestamp, const char *formatted_message, char *output_buffer)"
.PP
format the callsite and timestamp info according to the format set using \fBqb_log_format_set()\fP It is intended to be used from your custom logger function\&.
.SS "void* \fBqb_log_target_user_data_get\fP (int32_tt)"
.SS "void* qb_log_target_user_data_get (int32_tt)"
.PP
Retrieve the user data set by either qb_log_custom_open or qb_log_target_user_data_set\&.
.SS "int32_t \fBqb_log_target_user_data_set\fP (int32_tt, void *user_data)"
.SS "int32_t qb_log_target_user_data_set (int32_tt, void *user_data)"
.PP
Associate user data with this log target\&. \fBNote:\fP
@ -876,7 +886,7 @@ only use this with custom targets
.RE
.PP
.SS "int32_t \fBqb_log_thread_priority_set\fP (int32_tpolicy, int32_tpriority)"
.SS "int32_t qb_log_thread_priority_set (int32_tpolicy, int32_tpriority)"
.PP
When using threaded logging set the pthread policy and priority\&. \fBReturn values:\fP
@ -887,31 +897,31 @@ When using threaded logging set the pthread policy and priority\&. \fBReturn val
.RE
.PP
.SS "int32_t \fBqb_log_thread_start\fP (void)"
.SS "int32_t qb_log_thread_start (void)"
.PP
Start the logging pthread\&.
.SH "Variable Documentation"
.PP
.SS "enum \fBqb_log_target_state\fP \fB__attribute__\fP"
.SS "enum \fBqb_log_target_state\fP __attribute__"
.SS "struct \fBqb_log_callsite\fP \fB__start___verbose\fP[]"
.SS "struct \fBqb_log_callsite\fP __start___verbose[]"
.SS "struct \fBqb_log_callsite\fP \fB__stop___verbose\fP[]"
.SS "struct \fBqb_log_callsite\fP __stop___verbose[]"
.SS "const char* \fBfilename\fP"
.SS "const char* filename"
.SS "const char* \fBformat\fP"
.SS "const char* format"
.SS "const char* \fBfunction\fP"
.SS "const char* function"
.SS "uint32_t \fBlineno\fP"
.SS "uint32_t lineno"
.SS "uint8_t \fBpriority\fP"
.SS "uint8_t priority"
.SS "uint32_t \fBtags\fP"
.SS "uint32_t tags"
.SS "uint32_t \fBtargets\fP"
.SS "uint32_t targets"
.SH "Author"
.PP

View File

@ -1,4 +1,4 @@
.TH "qbloop.h" 3 "Sun Mar 11 2012" "Version 0.11.1" "libqb" \" -*- nroff -*-
.TH "qbloop.h" 3 "Mon Sep 10 2012" "Version 0.14.2" "libqb" \" -*- nroff -*-
.ad l
.nh
.SH NAME
@ -110,11 +110,11 @@ Main loop manages timers, jobs and polling sockets\&.
.br
.RI "\fIDelete a poll job\&. \fP"
.ti -1c
.RI "int32_t \fBqb_loop_signal_add\fP (\fBqb_loop_t\fP *l, enum \fBqb_loop_priority\fP p, int32_t signal, void *data, \fBqb_loop_signal_dispatch_fn\fP dispatch_fn, \fBqb_loop_signal_handle\fP *handle)"
.RI "int32_t \fBqb_loop_signal_add\fP (\fBqb_loop_t\fP *l, enum \fBqb_loop_priority\fP p, int32_t sig, void *data, \fBqb_loop_signal_dispatch_fn\fP dispatch_fn, \fBqb_loop_signal_handle\fP *handle)"
.br
.RI "\fIAdd a signal job\&. \fP"
.ti -1c
.RI "int32_t \fBqb_loop_signal_mod\fP (\fBqb_loop_t\fP *l, enum \fBqb_loop_priority\fP p, int32_t signal, void *data, \fBqb_loop_signal_dispatch_fn\fP dispatch_fn, \fBqb_loop_signal_handle\fP handle)"
.RI "int32_t \fBqb_loop_signal_mod\fP (\fBqb_loop_t\fP *l, enum \fBqb_loop_priority\fP p, int32_t sig, void *data, \fBqb_loop_signal_dispatch_fn\fP dispatch_fn, \fBqb_loop_signal_handle\fP handle)"
.br
.RI "\fIModify the signal job\&. \fP"
.ti -1c
@ -129,13 +129,13 @@ Main loop manages timers, jobs and polling sockets\&.
.SH "Typedef Documentation"
.PP
.SS "typedef void(* \fBqb_loop_job_dispatch_fn\fP)(void *data)"
.SS "typedef void(* qb_loop_job_dispatch_fn)(void *data)"
.SS "typedef int32_t(* \fBqb_loop_poll_dispatch_fn\fP)(int32_t fd, int32_t revents, void *data)"
.SS "typedef int32_t(* qb_loop_poll_dispatch_fn)(int32_t fd, int32_t revents, void *data)"
.SS "typedef void(* \fBqb_loop_poll_low_fds_event_fn\fP)(int32_t not_enough, int32_t fds_available)"
.SS "typedef void(* qb_loop_poll_low_fds_event_fn)(int32_t not_enough, int32_t fds_available)"
.SS "typedef int32_t(* \fBqb_loop_signal_dispatch_fn\fP)(int32_t rsignal, void *data)"
.SS "typedef int32_t(* qb_loop_signal_dispatch_fn)(int32_t rsignal, void *data)"
.SS "typedef void* \fBqb_loop_signal_handle\fP"
@ -143,7 +143,7 @@ Main loop manages timers, jobs and polling sockets\&.
.PP
An opaque data type representing the main loop\&.
.SS "typedef void(* \fBqb_loop_timer_dispatch_fn\fP)(void *data)"
.SS "typedef void(* qb_loop_timer_dispatch_fn)(void *data)"
.SS "typedef uint64_t \fBqb_loop_timer_handle\fP"
@ -165,7 +165,7 @@ Priorites for jobs, timers & poll\&.
.SH "Function Documentation"
.PP
.SS "\fBqb_loop_t\fP* \fBqb_loop_create\fP (void)"
.SS "\fBqb_loop_t\fP* qb_loop_create (void)"
.PP
Create a new main loop\&. \fBReturns:\fP
@ -174,9 +174,9 @@ loop instance\&.
.RE
.PP
.SS "void \fBqb_loop_destroy\fP (struct qb_loop *l)"
.SS "void qb_loop_destroy (struct qb_loop *l)"
.SS "int32_t \fBqb_loop_job_add\fP (\fBqb_loop_t\fP *l, enum \fBqb_loop_priority\fPp, void *data, \fBqb_loop_job_dispatch_fn\fPdispatch_fn)"
.SS "int32_t qb_loop_job_add (\fBqb_loop_t\fP *l, enum \fBqb_loop_priority\fPp, void *data, \fBqb_loop_job_dispatch_fn\fPdispatch_fn)"
.PP
Add a job to the mainloop\&. This is run in the next cycle of the loop\&.
@ -203,7 +203,7 @@ status (0 == ok, -errno == failure)
.RE
.PP
.SS "int32_t \fBqb_loop_job_del\fP (struct qb_loop *l, enum \fBqb_loop_priority\fPp, void *data, \fBqb_loop_job_dispatch_fn\fPdispatch_fn)"
.SS "int32_t qb_loop_job_del (struct qb_loop *l, enum \fBqb_loop_priority\fPp, void *data, \fBqb_loop_job_dispatch_fn\fPdispatch_fn)"
.PP
Delete a job from the mainloop\&. This will try to delete the job if it hasn't run yet\&.
@ -230,7 +230,7 @@ status (0 == ok, -errno == failure)
.RE
.PP
.SS "int32_t \fBqb_loop_poll_add\fP (\fBqb_loop_t\fP *l, enum \fBqb_loop_priority\fPp, int32_tfd, int32_tevents, void *data, \fBqb_loop_poll_dispatch_fn\fPdispatch_fn)"
.SS "int32_t qb_loop_poll_add (\fBqb_loop_t\fP *l, enum \fBqb_loop_priority\fPp, int32_tfd, int32_tevents, void *data, \fBqb_loop_poll_dispatch_fn\fPdispatch_fn)"
.PP
Add a poll job to the mainloop\&. \fBNote:\fP
@ -259,7 +259,7 @@ status (0 == ok, -errno == failure)
.RE
.PP
.SS "int32_t \fBqb_loop_poll_del\fP (\fBqb_loop_t\fP *l, int32_tfd)"
.SS "int32_t qb_loop_poll_del (\fBqb_loop_t\fP *l, int32_tfd)"
.PP
Delete a poll job\&. \fBParameters:\fP
@ -275,7 +275,7 @@ status (0 == ok, -errno == failure)
.RE
.PP
.SS "int32_t \fBqb_loop_poll_low_fds_event_set\fP (\fBqb_loop_t\fP *l, \fBqb_loop_poll_low_fds_event_fn\fPfn)"
.SS "int32_t qb_loop_poll_low_fds_event_set (\fBqb_loop_t\fP *l, \fBqb_loop_poll_low_fds_event_fn\fPfn)"
.PP
Set a callback to receive events on file descriptors getting low\&. \fBParameters:\fP
@ -291,7 +291,7 @@ status (0 == ok, -errno == failure)
.RE
.PP
.SS "int32_t \fBqb_loop_poll_mod\fP (\fBqb_loop_t\fP *l, enum \fBqb_loop_priority\fPp, int32_tfd, int32_tevents, void *data, \fBqb_loop_poll_dispatch_fn\fPdispatch_fn)"
.SS "int32_t qb_loop_poll_mod (\fBqb_loop_t\fP *l, enum \fBqb_loop_priority\fPp, int32_tfd, int32_tevents, void *data, \fBqb_loop_poll_dispatch_fn\fPdispatch_fn)"
.PP
Modify a poll job\&. \fBParameters:\fP
@ -315,7 +315,7 @@ status (0 == ok, -errno == failure)
.RE
.PP
.SS "void \fBqb_loop_run\fP (\fBqb_loop_t\fP *l)"
.SS "void qb_loop_run (\fBqb_loop_t\fP *l)"
.PP
Run the main loop\&. \fBParameters:\fP
@ -324,7 +324,7 @@ Run the main loop\&. \fBParameters:\fP
.RE
.PP
.SS "int32_t \fBqb_loop_signal_add\fP (\fBqb_loop_t\fP *l, enum \fBqb_loop_priority\fPp, int32_tsignal, void *data, \fBqb_loop_signal_dispatch_fn\fPdispatch_fn, \fBqb_loop_signal_handle\fP *handle)"
.SS "int32_t qb_loop_signal_add (\fBqb_loop_t\fP *l, enum \fBqb_loop_priority\fPp, int32_tsig, void *data, \fBqb_loop_signal_dispatch_fn\fPdispatch_fn, \fBqb_loop_signal_handle\fP *handle)"
.PP
Add a signal job\&. Get a callback on this signal (not in the context of the signal)\&.
@ -335,7 +335,7 @@ Add a signal job\&. Get a callback on this signal (not in the context of the sig
.br
\fIp\fP the priority
.br
\fIsignal\fP (SIGHUP or SIGINT) etc \&.\&.\&.\&.
\fIsig\fP (SIGHUP or SIGINT) etc \&.\&.\&.\&.
.br
\fIdata\fP user data passed into the dispatch function
.br
@ -350,7 +350,7 @@ status (0 == ok, -errno == failure)
.RE
.PP
.SS "int32_t \fBqb_loop_signal_del\fP (\fBqb_loop_t\fP *l, \fBqb_loop_signal_handle\fPhandle)"
.SS "int32_t qb_loop_signal_del (\fBqb_loop_t\fP *l, \fBqb_loop_signal_handle\fPhandle)"
.PP
Delete the signal job\&. \fBParameters:\fP
@ -366,7 +366,7 @@ status (0 == ok, -errno == failure)
.RE
.PP
.SS "int32_t \fBqb_loop_signal_mod\fP (\fBqb_loop_t\fP *l, enum \fBqb_loop_priority\fPp, int32_tsignal, void *data, \fBqb_loop_signal_dispatch_fn\fPdispatch_fn, \fBqb_loop_signal_handle\fPhandle)"
.SS "int32_t qb_loop_signal_mod (\fBqb_loop_t\fP *l, enum \fBqb_loop_priority\fPp, int32_tsig, void *data, \fBqb_loop_signal_dispatch_fn\fPdispatch_fn, \fBqb_loop_signal_handle\fPhandle)"
.PP
Modify the signal job\&. \fBParameters:\fP
@ -375,7 +375,7 @@ Modify the signal job\&. \fBParameters:\fP
.br
\fIp\fP the priority
.br
\fIsignal\fP (SIGHUP or SIGINT) etc \&.\&.\&.\&.
\fIsig\fP (SIGHUP or SIGINT) etc \&.\&.\&.\&.
.br
\fIdata\fP user data passed into the dispatch function
.br
@ -390,7 +390,7 @@ status (0 == ok, -errno == failure)
.RE
.PP
.SS "void \fBqb_loop_stop\fP (\fBqb_loop_t\fP *l)"
.SS "void qb_loop_stop (\fBqb_loop_t\fP *l)"
.PP
Stop the main loop\&. \fBParameters:\fP
@ -399,7 +399,7 @@ Stop the main loop\&. \fBParameters:\fP
.RE
.PP
.SS "int32_t \fBqb_loop_timer_add\fP (\fBqb_loop_t\fP *l, enum \fBqb_loop_priority\fPp, uint64_tnsec_duration, void *data, \fBqb_loop_timer_dispatch_fn\fPdispatch_fn, \fBqb_loop_timer_handle\fP *timer_handle_out)"
.SS "int32_t qb_loop_timer_add (\fBqb_loop_t\fP *l, enum \fBqb_loop_priority\fPp, uint64_tnsec_duration, void *data, \fBqb_loop_timer_dispatch_fn\fPdispatch_fn, \fBqb_loop_timer_handle\fP *timer_handle_out)"
.PP
Add a timer to the mainloop\&. \fBNote:\fP
@ -428,7 +428,7 @@ status (0 == ok, -errno == failure)
.RE
.PP
.SS "int32_t \fBqb_loop_timer_del\fP (\fBqb_loop_t\fP *l, \fBqb_loop_timer_handle\fPth)"
.SS "int32_t qb_loop_timer_del (\fBqb_loop_t\fP *l, \fBqb_loop_timer_handle\fPth)"
.PP
Delete a timer that is still outstanding\&. \fBParameters:\fP
@ -444,7 +444,7 @@ status (0 == ok, -errno == failure)
.RE
.PP
.SS "uint64_t \fBqb_loop_timer_expire_time_get\fP (struct qb_loop *l, \fBqb_loop_timer_handle\fPth)"
.SS "uint64_t qb_loop_timer_expire_time_get (struct qb_loop *l, \fBqb_loop_timer_handle\fPth)"
.PP
Get the time remaining before it expires\&. \fBNote:\fP
@ -465,7 +465,7 @@ nano seconds left
.RE
.PP
.SS "int32_t \fBqb_loop_timer_is_running\fP (\fBqb_loop_t\fP *l, \fBqb_loop_timer_handle\fPth)"
.SS "int32_t qb_loop_timer_is_running (\fBqb_loop_t\fP *l, \fBqb_loop_timer_handle\fPth)"
.PP
Check to see if a timer that is still outstanding\&. \fBParameters:\fP

View File

@ -1,4 +1,4 @@
.TH "qbmap.h" 3 "Sun Mar 11 2012" "Version 0.11.1" "libqb" \" -*- nroff -*-
.TH "qbmap.h" 3 "Mon Sep 10 2012" "Version 0.14.2" "libqb" \" -*- nroff -*-
.ad l
.nh
.SH NAME
@ -14,7 +14,7 @@ This provides a map interface to a Patricia trie, hashtable or skiplist\&.
\fC#include <unistd\&.h>\fP
.br
.SS "Defines"
.SS "Macros"
.in +1c
.ti -1c
@ -137,13 +137,13 @@ The hashtable is NOT ordered, but ptrie and skiplist are\&.
Below is a simple example of how to iterate over a map\&.
.PP
.nf
const char *p;
void *data;
qb_map_iter_t *it = qb_map_iter_create(m);
for (p = qb_map_iter_next(it, &data); p; p = qb_map_iter_next(it, &data)) {
printf('%s > %s\n', p, (char*) data);
}
qb_map_iter_free(it);
const char *p;
void *data;
qb_map_iter_t *it = qb_map_iter_create(m);
for (p = qb_map_iter_next(it, &data); p; p = qb_map_iter_next(it, &data)) {
printf('%s > %s\n', p, (char*) data);
}
qb_map_iter_free(it);
.fi
.PP
@ -152,7 +152,7 @@ Below is a simple example of how to iterate over a map\&.
Deletion of items within the iterator is supported\&. But note do not free the item memory in the iterator\&. If you need to free the data items then register for a notifier and free the memory there\&. This is required as the items are reference counted\&.
.PP
.nf
qb_map_notify_add(m, NULL, my_map_free_handler,
qb_map_notify_add(m, NULL, my_map_free_handler,
QB_MAP_NOTIFY_FREE, NULL);
.fi
@ -180,18 +180,18 @@ The ptrie supports prefixes in the iterator:
.PP
.PP
.nf
it = qb_map_pref_iter_create(m, 'aa');
while ((p = qb_map_iter_next(it, &data)) != NULL) {
printf('%s > %s\n', p, (char*)data);
}
qb_map_iter_free(it);
it = qb_map_pref_iter_create(m, 'aa');
while ((p = qb_map_iter_next(it, &data)) != NULL) {
printf('%s > %s\n', p, (char*)data);
}
qb_map_iter_free(it);
.fi
.PP
.PP
The ptrie also supports prefixes in notifications: (remember to pass QB_MAP_NOTIFY_RECURSIVE into the notify_add\&.
.PP
.nf
qb_map_notify_add(m, 'root', my_map_notification,
qb_map_notify_add(m, 'root', my_map_notification,
(QB_MAP_NOTIFY_INSERTED|
QB_MAP_NOTIFY_DELETED|
QB_MAP_NOTIFY_REPLACED|
@ -201,17 +201,17 @@ The ptrie also supports prefixes in notifications: (remember to pass QB_MAP_NOTI
.fi
.PP
.SH "Define Documentation"
.SH "Macro Definition Documentation"
.PP
.SS "#define \fBQB_MAP_NOTIFY_DELETED\fP 1"
.SS "#define QB_MAP_NOTIFY_DELETED 1"
.SS "#define \fBQB_MAP_NOTIFY_FREE\fP 16"
.SS "#define QB_MAP_NOTIFY_FREE 16"
.SS "#define \fBQB_MAP_NOTIFY_INSERTED\fP 4"
.SS "#define QB_MAP_NOTIFY_INSERTED 4"
.SS "#define \fBQB_MAP_NOTIFY_RECURSIVE\fP 8"
.SS "#define QB_MAP_NOTIFY_RECURSIVE 8"
.SS "#define \fBQB_MAP_NOTIFY_REPLACED\fP 2"
.SS "#define QB_MAP_NOTIFY_REPLACED 2"
.SH "Typedef Documentation"
.PP
@ -219,17 +219,17 @@ The ptrie also supports prefixes in notifications: (remember to pass QB_MAP_NOTI
.PP
This is an opaque data type representing an iterator instance\&.
.SS "typedef void(* \fBqb_map_notify_fn\fP)(uint32_t event, char *key, void *old_value, void *value, void *user_data)"
.SS "typedef void(* qb_map_notify_fn)(uint32_t event, char *key, void *old_value, void *value, void *user_data)"
.SS "typedef struct qb_map \fBqb_map_t\fP"
.PP
This is an opaque data type representing an instance of a map\&.
.SS "typedef int32_t(* \fBqb_map_transverse_fn\fP)(const char *key, void *value, void *user_data)"
.SS "typedef int32_t(* qb_map_transverse_fn)(const char *key, void *value, void *user_data)"
.SH "Function Documentation"
.PP
.SS "\fBqb_map_t\fP* \fBqb_hashtable_create\fP (size_tmax_size)"
.SS "\fBqb_map_t\fP* qb_hashtable_create (size_tmax_size)"
.PP
Create an unsorted map based on a hashtable\&. \fBParameters:\fP
@ -243,19 +243,19 @@ the map instance
.RE
.PP
.SS "size_t \fBqb_map_count_get\fP (\fBqb_map_t\fP *map)"
.SS "size_t qb_map_count_get (\fBqb_map_t\fP *map)"
.PP
Get the number of items in the map\&.
.SS "void \fBqb_map_destroy\fP (\fBqb_map_t\fP *map)"
.SS "void qb_map_destroy (\fBqb_map_t\fP *map)"
.PP
Destroy the map, removes all the items from the map\&.
.SS "void \fBqb_map_foreach\fP (\fBqb_map_t\fP *map, \fBqb_map_transverse_fn\fPfunc, void *user_data)"
.SS "void qb_map_foreach (\fBqb_map_t\fP *map, \fBqb_map_transverse_fn\fPfunc, void *user_data)"
.PP
Calls the given function for each of the key/value pairs in the map\&. The function is passed the key and value of each pair, and the given data parameter\&. The map is traversed in sorted order\&.
.SS "void* \fBqb_map_get\fP (\fBqb_map_t\fP *map, const char *key)"
.SS "void* qb_map_get (\fBqb_map_t\fP *map, const char *key)"
.PP
Gets the value corresponding to the given key\&. \fBReturn values:\fP
@ -266,11 +266,11 @@ Gets the value corresponding to the given key\&. \fBReturn values:\fP
.RE
.PP
.SS "\fBqb_map_iter_t\fP* \fBqb_map_iter_create\fP (\fBqb_map_t\fP *map)"
.SS "\fBqb_map_iter_t\fP* qb_map_iter_create (\fBqb_map_t\fP *map)"
.PP
Create an iterator\&.
.SS "void \fBqb_map_iter_free\fP (\fBqb_map_iter_t\fP *i)"
.SS "void qb_map_iter_free (\fBqb_map_iter_t\fP *i)"
.PP
free the iterator \fBParameters:\fP
@ -279,7 +279,7 @@ free the iterator \fBParameters:\fP
.RE
.PP
.SS "const char* \fBqb_map_iter_next\fP (\fBqb_map_iter_t\fP *i, void **value)"
.SS "const char* qb_map_iter_next (\fBqb_map_iter_t\fP *i, void **value)"
.PP
Get the next item\&. \fBParameters:\fP
@ -297,7 +297,7 @@ Get the next item\&. \fBParameters:\fP
.RE
.PP
.SS "int32_t \fBqb_map_notify_add\fP (\fBqb_map_t\fP *m, const char *key, \fBqb_map_notify_fn\fPfn, int32_tevents, void *user_data)"
.SS "int32_t qb_map_notify_add (\fBqb_map_t\fP *m, const char *key, \fBqb_map_notify_fn\fPfn, int32_tevents, void *user_data)"
.PP
Add a notifier to the map\&. \fBParameters:\fP
@ -328,7 +328,7 @@ you can use key prefixes with trie maps\&.
.RE
.PP
.SS "int32_t \fBqb_map_notify_del\fP (\fBqb_map_t\fP *m, const char *key, \fBqb_map_notify_fn\fPfn, int32_tevents)"
.SS "int32_t qb_map_notify_del (\fBqb_map_t\fP *m, const char *key, \fBqb_map_notify_fn\fPfn, int32_tevents)"
.PP
Delete a notifier from the map\&. \fBNote:\fP
@ -355,7 +355,7 @@ the key,fn and events must match those you added\&.
.RE
.PP
.SS "int32_t \fBqb_map_notify_del_2\fP (\fBqb_map_t\fP *m, const char *key, \fBqb_map_notify_fn\fPfn, int32_tevents, void *user_data)"
.SS "int32_t qb_map_notify_del_2 (\fBqb_map_t\fP *m, const char *key, \fBqb_map_notify_fn\fPfn, int32_tevents, void *user_data)"
.PP
Delete a notifier from the map (including the userdata)\&. \fBNote:\fP
@ -384,7 +384,7 @@ the key, fn, events and userdata must match those you added\&.
.RE
.PP
.SS "\fBqb_map_iter_t\fP* \fBqb_map_pref_iter_create\fP (\fBqb_map_t\fP *map, const char *prefix)"
.SS "\fBqb_map_iter_t\fP* qb_map_pref_iter_create (\fBqb_map_t\fP *map, const char *prefix)"
.PP
Create a prefix iterator\&. This will iterate over all items with the given prefix\&.
@ -395,15 +395,15 @@ this is only supported by the trie\&.
.RE
.PP
.SS "void \fBqb_map_put\fP (\fBqb_map_t\fP *map, const char *key, const void *value)"
.SS "void qb_map_put (\fBqb_map_t\fP *map, const char *key, const void *value)"
.PP
Inserts a new key and value into a qb_map_t\&. If the key already exists in the qb_map_t, it gets replaced by the new key\&.
.SS "int32_t \fBqb_map_rm\fP (\fBqb_map_t\fP *map, const char *key)"
.SS "int32_t qb_map_rm (\fBqb_map_t\fP *map, const char *key)"
.PP
Removes a key/value pair from a map\&.
.SS "\fBqb_map_t\fP* \fBqb_skiplist_create\fP (void)"
.SS "\fBqb_map_t\fP* qb_skiplist_create (void)"
.PP
Create a sorted map using a skiplist\&. \fBReturns:\fP
@ -412,11 +412,11 @@ the map instance
.RE
.PP
.SS "\fBqb_map_t\fP* \fBqb_trie_create\fP (void)"
.SS "\fBqb_map_t\fP* qb_trie_create (void)"
.PP
Create a sorted map using a Patricia trie or 'Radix tree'\&.
.SS "void \fBqb_trie_dump\fP (\fBqb_map_t\fP *m)"
.SS "void qb_trie_dump (\fBqb_map_t\fP *m)"
.PP
print out the nodes in the trie (for debug purposes)

View File

@ -1,4 +1,4 @@
.TH "qbutil.h" 3 "Sun Mar 11 2012" "Version 0.11.1" "libqb" \" -*- nroff -*-
.TH "qbutil.h" 3 "Mon Sep 10 2012" "Version 0.14.2" "libqb" \" -*- nroff -*-
.ad l
.nh
.SH NAME
@ -15,7 +15,7 @@ qbutil.h \-
\fC#include <qb/qbdefs\&.h>\fP
.br
.SS "Defines"
.SS "Macros"
.in +1c
.ti -1c
@ -180,21 +180,21 @@ These are some convience functions used throughout libqb\&.
.PP
.nf
uint64_t elapsed1;
uint64_t elapsed2;
qb_util_stopwatch_t *sw = qb_util_stopwatch_create();
qb_util_stopwatch_start(sw);
usleep(sometime);
qb_util_stopwatch_stop(sw);
elapsed1 = qb_util_stopwatch_us_elapsed_get(sw);
usleep(somemoretime);
qb_util_stopwatch_stop(sw);
elapsed2 = qb_util_stopwatch_us_elapsed_get(sw);
qb_util_stopwatch_free(sw);
uint64_t elapsed1;
uint64_t elapsed2;
qb_util_stopwatch_t *sw = qb_util_stopwatch_create();
qb_util_stopwatch_start(sw);
usleep(sometime);
qb_util_stopwatch_stop(sw);
elapsed1 = qb_util_stopwatch_us_elapsed_get(sw);
usleep(somemoretime);
qb_util_stopwatch_stop(sw);
elapsed2 = qb_util_stopwatch_us_elapsed_get(sw);
qb_util_stopwatch_free(sw);
.fi
.PP
@ -207,44 +207,44 @@ Setup a stopwatch with space for 3 splits\&.
.PP
.PP
.nf
uint64_t split;
qb_util_stopwatch_t *sw = qb_util_stopwatch_create();
qb_util_stopwatch_split_ctl(sw, 3, 0);
qb_util_stopwatch_start(sw);
usleep(sometime);
qb_util_stopwatch_split(sw);
usleep(somemoretime);
qb_util_stopwatch_split(sw);
usleep(somemoretime);
qb_util_stopwatch_split(sw);
idx = qb_util_stopwatch_split_last(sw);
do {
split = qb_util_stopwatch_time_split_get(sw, idx, idx);
qb_log(LOG_INFO, 'split %d is %'PRIu64'', last, split);
idx--;
} while (split > 0);
split = qb_util_stopwatch_time_split_get(sw, 2, 1);
qb_log(LOG_INFO, 'time between second and third split is %'PRIu64'', split);
qb_util_stopwatch_free(sw);
uint64_t split;
qb_util_stopwatch_t *sw = qb_util_stopwatch_create();
qb_util_stopwatch_split_ctl(sw, 3, 0);
qb_util_stopwatch_start(sw);
usleep(sometime);
qb_util_stopwatch_split(sw);
usleep(somemoretime);
qb_util_stopwatch_split(sw);
usleep(somemoretime);
qb_util_stopwatch_split(sw);
idx = qb_util_stopwatch_split_last(sw);
do {
split = qb_util_stopwatch_time_split_get(sw, idx, idx);
qb_log(LOG_INFO, 'split %d is %'PRIu64'', last, split);
idx--;
} while (split > 0);
split = qb_util_stopwatch_time_split_get(sw, 2, 1);
qb_log(LOG_INFO, 'time between second and third split is %'PRIu64'', split);
qb_util_stopwatch_free(sw);
.fi
.PP
.SH "Define Documentation"
.SH "Macro Definition Documentation"
.PP
.SS "#define \fBQB_UTIL_SW_OVERWRITE\fP 0x01"
.SS "#define QB_UTIL_SW_OVERWRITE 0x01"
.SH "Typedef Documentation"
.PP
.SS "typedef struct qb_thread_lock_s \fBqb_thread_lock_t\fP"
.SS "typedef void(* \fBqb_util_log_fn_t\fP)(const char *file_name, int32_t file_line, int32_t severity, const char *msg)"
.SS "typedef void(* qb_util_log_fn_t)(const char *file_name, int32_t file_line, int32_t severity, const char *msg)"
.SS "typedef struct qb_util_stopwatch \fBqb_util_stopwatch_t\fP"
@ -264,15 +264,15 @@ QB_THREAD_LOCK_SHORT is a short term lock (spinlock if available on your system)
.SH "Function Documentation"
.PP
.SS "char* \fBqb_strerror_r\fP (interrnum, char *buf, size_tbuflen)"
.SS "char* qb_strerror_r (interrnum, char *buf, size_tbuflen)"
.PP
strerror_r replacement\&.
.SS "int32_t \fBqb_thread_lock\fP (\fBqb_thread_lock_t\fP *tl)"
.SS "int32_t qb_thread_lock (\fBqb_thread_lock_t\fP *tl)"
.PP
Calls either pthread_mutex_lock() or pthread_spin_lock()\&.
.SS "\fBqb_thread_lock_t\fP* \fBqb_thread_lock_create\fP (\fBqb_thread_lock_type_t\fPtype)"
.SS "\fBqb_thread_lock_t\fP* qb_thread_lock_create (\fBqb_thread_lock_type_t\fPtype)"
.PP
Create a new lock of the given type\&. \fBParameters:\fP
@ -286,19 +286,19 @@ pointer to qb_thread_lock_type_t or NULL on error\&.
.RE
.PP
.SS "int32_t \fBqb_thread_lock_destroy\fP (\fBqb_thread_lock_t\fP *tl)"
.SS "int32_t qb_thread_lock_destroy (\fBqb_thread_lock_t\fP *tl)"
.PP
Calls either pthread_mutex_destro() or pthread_spin_destroy()\&.
.SS "int32_t \fBqb_thread_trylock\fP (\fBqb_thread_lock_t\fP *tl)"
.SS "int32_t qb_thread_trylock (\fBqb_thread_lock_t\fP *tl)"
.PP
Calls either pthread_mutex_trylock() or pthread_spin_trylock()\&.
.SS "int32_t \fBqb_thread_unlock\fP (\fBqb_thread_lock_t\fP *tl)"
.SS "int32_t qb_thread_unlock (\fBqb_thread_lock_t\fP *tl)"
.PP
Calls either pthread_mutex_unlock() or pthread_spin_unlock\&.
.SS "void \fBqb_timespec_add_ms\fP (struct timespec *ts, int32_tms)"
.SS "void qb_timespec_add_ms (struct timespec *ts, int32_tms)"
.PP
Add milliseconds onto the timespec\&. \fBParameters:\fP
@ -309,35 +309,35 @@ Add milliseconds onto the timespec\&. \fBParameters:\fP
.RE
.PP
.SS "uint64_t \fBqb_util_nano_current_get\fP (void)"
.SS "uint64_t qb_util_nano_current_get (void)"
.PP
Get the current number of nano secounds produced by the systems incrementing clock (CLOCK_MONOTOMIC if available)\&.
.SS "uint64_t \fBqb_util_nano_from_epoch_get\fP (void)"
.SS "uint64_t qb_util_nano_from_epoch_get (void)"
.PP
Get the time in nano seconds since epoch\&.
.SS "uint64_t \fBqb_util_nano_monotonic_hz\fP (void)"
.SS "uint64_t qb_util_nano_monotonic_hz (void)"
.PP
Get the frequence of the clock used in \fBqb_util_nano_current_get()\fP\&.
.SS "void \fBqb_util_set_log_function\fP (\fBqb_util_log_fn_t\fPfn)"
.SS "void qb_util_set_log_function (\fBqb_util_log_fn_t\fPfn)"
.PP
Use this function to output libqb internal log message as you wish\&.
.SS "\fBqb_util_stopwatch_t\fP* \fBqb_util_stopwatch_create\fP (void)"
.SS "\fBqb_util_stopwatch_t\fP* qb_util_stopwatch_create (void)"
.PP
Create a Stopwatch (to time operations)
.SS "void \fBqb_util_stopwatch_free\fP (\fBqb_util_stopwatch_t\fP *sw)"
.SS "void qb_util_stopwatch_free (\fBqb_util_stopwatch_t\fP *sw)"
.PP
Free the stopwatch\&.
.SS "float \fBqb_util_stopwatch_sec_elapsed_get\fP (\fBqb_util_stopwatch_t\fP *sw)"
.SS "float qb_util_stopwatch_sec_elapsed_get (\fBqb_util_stopwatch_t\fP *sw)"
.PP
Get the elapsed time in seconds\&. (it must have been started and stopped)\&.
.SS "uint64_t \fBqb_util_stopwatch_split\fP (\fBqb_util_stopwatch_t\fP *sw)"
.SS "uint64_t qb_util_stopwatch_split (\fBqb_util_stopwatch_t\fP *sw)"
.PP
Create a new time split (or lap time) \fBParameters:\fP
@ -353,7 +353,7 @@ Create a new time split (or lap time) \fBParameters:\fP
.RE
.PP
.SS "int32_t \fBqb_util_stopwatch_split_ctl\fP (\fBqb_util_stopwatch_t\fP *sw, uint32_tmax_splits, uint32_toptions)"
.SS "int32_t qb_util_stopwatch_split_ctl (\fBqb_util_stopwatch_t\fP *sw, uint32_tmax_splits, uint32_toptions)"
\fBParameters:\fP
.RS 4
\fIsw\fP the stopwatch
@ -371,7 +371,7 @@ Create a new time split (or lap time) \fBParameters:\fP
.RE
.PP
.SS "uint32_t \fBqb_util_stopwatch_split_last\fP (\fBqb_util_stopwatch_t\fP *sw)"
.SS "uint32_t qb_util_stopwatch_split_last (\fBqb_util_stopwatch_t\fP *sw)"
.PP
Get the last split index to be used by \fBqb_util_stopwatch_time_split_get()\fP \fBNote:\fP
@ -390,15 +390,15 @@ the last entry index
.RE
.PP
.SS "void \fBqb_util_stopwatch_start\fP (\fBqb_util_stopwatch_t\fP *sw)"
.SS "void qb_util_stopwatch_start (\fBqb_util_stopwatch_t\fP *sw)"
.PP
Start the stopwatch\&. This also acts as a reset\&. Essentially it sets the starting time and clears the splits\&.
.SS "void \fBqb_util_stopwatch_stop\fP (\fBqb_util_stopwatch_t\fP *sw)"
.SS "void qb_util_stopwatch_stop (\fBqb_util_stopwatch_t\fP *sw)"
.PP
Stop the stopwatch\&. This just allows you to get the elapsed time\&. So you can call this multiple times\&. Do not call \fBqb_util_stopwatch_start()\fP unless you want to reset the stopwatch\&.
.SS "uint64_t \fBqb_util_stopwatch_time_split_get\fP (\fBqb_util_stopwatch_t\fP *sw, uint32_treceint, uint32_tolder)"
.SS "uint64_t qb_util_stopwatch_time_split_get (\fBqb_util_stopwatch_t\fP *sw, uint32_treceint, uint32_tolder)"
.PP
Read the time split (in us) from 'receint' to 'older'\&. If older == receint then the cumulated split will be returned (from the stopwatch start)\&.
@ -420,11 +420,11 @@ Read the time split (in us) from 'receint' to 'older'\&. If older == receint the
.RE
.PP
.SS "uint64_t \fBqb_util_stopwatch_us_elapsed_get\fP (\fBqb_util_stopwatch_t\fP *sw)"
.SS "uint64_t qb_util_stopwatch_us_elapsed_get (\fBqb_util_stopwatch_t\fP *sw)"
.PP
Get the elapsed time in micro seconds\&. (it must have been started and stopped)\&.
.SS "void \fBqb_util_timespec_from_epoch_get\fP (struct timespec *ts)"
.SS "void qb_util_timespec_from_epoch_get (struct timespec *ts)"
.PP
Get the time in timespec since epoch\&. \fBParameters:\fP

59
docs/man8/qb-blackbox.8 Normal file
View File

@ -0,0 +1,59 @@
.\"/*
.\" * Copyright (C) 2012 Red Hat, Inc.
.\" *
.\" * Author: Angus Salkeld <asalkeld@redhat.com>
.\" *
.\" * This file is part of libqb.
.\" *
.\" * libqb 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.
.\" *
.\" * libqb 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 libqb. If not, see <http://www.gnu.org/licenses/>.
.\" */
.TH QB-BLACKBOX 8 2012-05-28
.SH NAME
qb-blackbox \- Display "flight data" from the "blackbox".
.SH SYNOPSIS
.B "qb-blackbox <blackbox files>..."
.SH DESCRIPTION
.B qb-blackbox
Print out the logs (including debug logs) that were recorded using libqb's blackbox.
.SH EXAMPLES
.TP
Get info to help developers diagnose a crash.
.br
$ qb-blackbox /var/lib/corosync/fdata
.br
Dumping the contents of /var/lib/corosync/fdata
.br
Mar 23 20:58:57 message_handler_orf_token():3677 install seq 0 aru 0 high seq received 0
.br
Mar 23 20:58:57 message_handler_orf_token():3696 retrans flag count 4 token aru 0 install seq 0 aru 0 0
.br
Mar 23 20:58:57 old_ring_state_reset():1487 Resetting old ring state
.br
Mar 23 20:58:57 deliver_messages_from_recovery_to_regular():1693 recovery to regular 1-0
.br
Mar 23 20:58:57 memb_state_operational_enter():1779 Delivering to app 1 to 0
.br
Mar 23 20:58:57 sync_abort():594 ENTERING sync_abort()
.br
Mar 23 20:58:57 sync_save_transitional():586 ENTERING sync_save_transitional()
.br
Mar 23 20:58:57 member_object_joined():301 Member joined: r(0) ip(192.168.122.1)
.br
Mar 23 20:58:57 sync_abort():594 ENTERING sync_abort()
.br
.SH SEE ALSO
.BR qblog.h (3),
.SH AUTHOR
Angus Salkeld
.PP

View File

@ -17,7 +17,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with libqb. If not, see <http://www.gnu.org/licenses/>.
#
MAINTAINERCLEANFILES = Makefiles.in
MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST =
CLEANFILES =
@ -25,27 +25,27 @@ noinst_PROGRAMS = mapnotify simplelog tcpclient tcpserver ipcclient ipcserver
mapnotify_SOURCES = mapnotify.c $(top_builddir)/include/qb/qbmap.h
mapnotify_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
mapnotify_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
mapnotify_LDADD = $(top_builddir)/lib/libqb.la
simplelog_SOURCES = simplelog.c $(top_builddir)/include/qb/qblog.h
simplelog_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
simplelog_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
simplelog_LDADD = $(top_builddir)/lib/libqb.la
tcpclient_SOURCES = tcpclient.c $(top_builddir)/include/qb/qbloop.h
tcpclient_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
tcpclient_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
tcpclient_LDADD = $(top_builddir)/lib/libqb.la
tcpserver_SOURCES = tcpserver.c $(top_builddir)/include/qb/qbloop.h
tcpserver_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
tcpserver_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
tcpserver_LDADD = $(top_builddir)/lib/libqb.la
ipcclient_SOURCES = ipcclient.c $(top_builddir)/include/qb/qbloop.h \
$(top_builddir)/include/qb/qbipcc.h
ipcclient_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
ipcclient_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
ipcclient_LDADD = $(top_builddir)/lib/libqb.la
ipcserver_SOURCES = ipcserver.c $(top_builddir)/include/qb/qbloop.h \
$(top_builddir)/include/qb/qbipcs.h
ipcserver_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include \
$(GLIB_CFLAGS)
ipcserver_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la $(GLIB_LIBS)
ipcserver_LDADD = $(top_builddir)/lib/libqb.la $(GLIB_LIBS)

View File

@ -54,34 +54,29 @@ CONFIG_CLEAN_VPATH_FILES =
PROGRAMS = $(noinst_PROGRAMS)
am_ipcclient_OBJECTS = ipcclient-ipcclient.$(OBJEXT)
ipcclient_OBJECTS = $(am_ipcclient_OBJECTS)
am__DEPENDENCIES_1 =
ipcclient_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(top_builddir)/lib/libqb.la
ipcclient_DEPENDENCIES = $(top_builddir)/lib/libqb.la
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am_ipcserver_OBJECTS = ipcserver-ipcserver.$(OBJEXT)
ipcserver_OBJECTS = $(am_ipcserver_OBJECTS)
ipcserver_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(top_builddir)/lib/libqb.la $(am__DEPENDENCIES_1)
am__DEPENDENCIES_1 =
ipcserver_DEPENDENCIES = $(top_builddir)/lib/libqb.la \
$(am__DEPENDENCIES_1)
am_mapnotify_OBJECTS = mapnotify-mapnotify.$(OBJEXT)
mapnotify_OBJECTS = $(am_mapnotify_OBJECTS)
mapnotify_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(top_builddir)/lib/libqb.la
mapnotify_DEPENDENCIES = $(top_builddir)/lib/libqb.la
am_simplelog_OBJECTS = simplelog-simplelog.$(OBJEXT)
simplelog_OBJECTS = $(am_simplelog_OBJECTS)
simplelog_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(top_builddir)/lib/libqb.la
simplelog_DEPENDENCIES = $(top_builddir)/lib/libqb.la
am_tcpclient_OBJECTS = tcpclient-tcpclient.$(OBJEXT)
tcpclient_OBJECTS = $(am_tcpclient_OBJECTS)
tcpclient_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(top_builddir)/lib/libqb.la
tcpclient_DEPENDENCIES = $(top_builddir)/lib/libqb.la
am_tcpserver_OBJECTS = tcpserver-tcpserver.$(OBJEXT)
tcpserver_OBJECTS = $(am_tcpserver_OBJECTS)
tcpserver_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(top_builddir)/lib/libqb.la
tcpserver_DEPENDENCIES = $(top_builddir)/lib/libqb.la
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include -I$(top_builddir)/include/qb
depcomp = $(SHELL) $(top_srcdir)/depcomp
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
@ -161,7 +156,6 @@ LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIB_RT = @LIB_RT@
LINT_FLAGS = @LINT_FLAGS@
LIPO = @LIPO@
LN_S = @LN_S@
@ -268,33 +262,33 @@ top_srcdir = @top_srcdir@
# You should have received a copy of the GNU Lesser General Public License
# along with libqb. If not, see <http://www.gnu.org/licenses/>.
#
MAINTAINERCLEANFILES = Makefiles.in
MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST =
CLEANFILES =
mapnotify_SOURCES = mapnotify.c $(top_builddir)/include/qb/qbmap.h
mapnotify_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
mapnotify_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
mapnotify_LDADD = $(top_builddir)/lib/libqb.la
simplelog_SOURCES = simplelog.c $(top_builddir)/include/qb/qblog.h
simplelog_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
simplelog_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
simplelog_LDADD = $(top_builddir)/lib/libqb.la
tcpclient_SOURCES = tcpclient.c $(top_builddir)/include/qb/qbloop.h
tcpclient_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
tcpclient_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
tcpclient_LDADD = $(top_builddir)/lib/libqb.la
tcpserver_SOURCES = tcpserver.c $(top_builddir)/include/qb/qbloop.h
tcpserver_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
tcpserver_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
tcpserver_LDADD = $(top_builddir)/lib/libqb.la
ipcclient_SOURCES = ipcclient.c $(top_builddir)/include/qb/qbloop.h \
$(top_builddir)/include/qb/qbipcc.h
ipcclient_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
ipcclient_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
ipcclient_LDADD = $(top_builddir)/lib/libqb.la
ipcserver_SOURCES = ipcserver.c $(top_builddir)/include/qb/qbloop.h \
$(top_builddir)/include/qb/qbipcs.h
ipcserver_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include \
$(GLIB_CFLAGS)
ipcserver_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la $(GLIB_LIBS)
ipcserver_LDADD = $(top_builddir)/lib/libqb.la $(GLIB_LIBS)
all: all-am
.SUFFIXES:

View File

@ -24,8 +24,15 @@
#include <qb/qbdefs.h>
#include <qb/qbutil.h>
#include <qb/qbipcc.h>
#include <qb/qblog.h>
#define MAX_MSG_SIZE (8192)
static int32_t do_benchmark = QB_FALSE;
static int32_t use_events = QB_FALSE;
static int alarm_notice;
static qb_util_stopwatch_t *sw;
#define ONE_MEG 1048576
#define MAX_MSG_SIZE ONE_MEG
static char data[ONE_MEG];
struct my_req {
struct qb_ipc_request_header hdr;
@ -37,22 +44,84 @@ struct my_res {
char message[256];
};
int
main(int argc, char *argv[])
static void sigalrm_handler (int num)
{
alarm_notice = 1;
}
static void
_benchmark(qb_ipcc_connection_t *conn, int write_size)
{
struct iovec iov[2];
unsigned int res;
struct qb_ipc_request_header hdr;
int write_count = 0;
float secs;
alarm_notice = 0;
hdr.size = write_size;
hdr.id = QB_IPC_MSG_USER_START + 1;
iov[0].iov_base = &hdr;
iov[0].iov_len = sizeof(struct qb_ipc_request_header);
iov[1].iov_base = data;
iov[1].iov_len = write_size - sizeof(struct qb_ipc_request_header);
alarm (10);
qb_util_stopwatch_start(sw);
do {
res = qb_ipcc_sendv(conn, iov, 2);
if (res == write_size) {
write_count++;
}
} while (alarm_notice == 0 && (res == write_size || res == -EAGAIN));
if (res < 0) {
perror("qb_ipcc_sendv");
}
qb_util_stopwatch_stop(sw);
secs = qb_util_stopwatch_sec_elapsed_get(sw);
printf ("%5d messages sent ", write_count);
printf ("%5d bytes per write ", write_size);
printf ("%7.3f Seconds runtime ", secs);
printf ("%9.3f TP/s ",
((float)write_count) / secs);
printf ("%7.3f MB/s.\n",
((float)write_count) * ((float)write_size) / secs);
}
static void
do_throughput_benchmark(qb_ipcc_connection_t *conn)
{
ssize_t size = 64;
int i;
signal (SIGALRM, sigalrm_handler);
sw = qb_util_stopwatch_create();
for (i = 0; i < 10; i++) { /* number of repetitions - up to 50k */
_benchmark (conn, size);
signal (SIGALRM, sigalrm_handler);
size *= 5;
if (size >= (ONE_MEG - 100)) {
break;
}
}
}
static void
do_echo(qb_ipcc_connection_t *conn)
{
qb_ipcc_connection_t *conn;
int32_t rc;
struct my_req req;
struct my_res res;
char *newline;
int32_t rc;
int32_t send_ten_events;
conn = qb_ipcc_connect("ipcserver", MAX_MSG_SIZE);
if (conn == NULL) {
perror("qb_ipcc_connect");
exit(1);
}
while(1) {
while (1) {
printf("SEND (q or Q to quit) : ");
if (fgets(req.message, 256, stdin) == NULL) {
continue;
@ -70,21 +139,99 @@ main(int argc, char *argv[])
rc = qb_ipcc_send(conn, &req, req.hdr.size);
if (rc < 0) {
perror("qb_ipcc_send");
exit(0);
}
}
send_ten_events = (strcasecmp(req.message, "events") == 0);
if (rc > 0) {
rc = qb_ipcc_recv(conn,
&res,
sizeof(res), -1);
if (use_events && !send_ten_events) {
printf("waiting for event recv\n");
rc = qb_ipcc_event_recv(conn, &res, sizeof(res), -1);
} else {
printf("waiting for recv\n");
rc = qb_ipcc_recv(conn, &res, sizeof(res), -1);
}
printf("recv %d\n", rc);
if (rc < 0) {
perror("qb_ipcc_recv");
exit(0);
}
if (send_ten_events) {
int32_t i;
printf("waiting for 10 events\n");
for (i = 0; i < 10; i++) {
rc = qb_ipcc_event_recv(conn, &res, sizeof(res), -1);
if (rc < 0) {
perror("qb_ipcc_event_recv");
} else {
printf("got event %d rc:%d\n", i, rc);
}
}
}
printf("Response[%d]: %s \n", res.hdr.id, res.message);
}
}
}
static void
show_usage(const char *name)
{
printf("usage: \n");
printf("%s <options>\n", name);
printf("\n");
printf(" options:\n");
printf("\n");
printf(" -h show this help text\n");
printf(" -b benchmark\n");
printf(" -e use events instead of responses\n");
printf("\n");
}
int
main(int argc, char *argv[])
{
qb_ipcc_connection_t *conn;
const char *options = "eb";
int32_t opt;
while ((opt = getopt(argc, argv, options)) != -1) {
switch (opt) {
case 'b':
do_benchmark = QB_TRUE;
break;
case 'e':
use_events = QB_TRUE;
break;
case 'h':
default:
show_usage(argv[0]);
exit(0);
break;
}
}
qb_log_init("ipcclient", LOG_USER, LOG_TRACE);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "*", LOG_TRACE);
qb_log_format_set(QB_LOG_STDERR, "%f:%l [%p] %b");
qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
conn = qb_ipcc_connect("ipcserver", MAX_MSG_SIZE);
if (conn == NULL) {
perror("qb_ipcc_connect");
exit(1);
}
if (do_benchmark) {
do_throughput_benchmark(conn);
} else {
do_echo(conn);
}
qb_ipcc_disconnect(conn);
return EXIT_SUCCESS;
}

View File

@ -34,11 +34,12 @@ static qb_array_t *gio_map;
#endif /* HAVE_GLIB */
static int32_t use_glib = QB_FALSE;
static int32_t use_events = QB_FALSE;
static qb_loop_t *bms_loop;
static qb_ipcs_service_t* s1;
static qb_ipcs_service_t *s1;
static int32_t
s1_connection_accept_fn(qb_ipcs_connection_t *c, uid_t uid, gid_t gid)
s1_connection_accept_fn(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
{
#if 0
if (uid == 0 && gid == 0) {
@ -52,34 +53,33 @@ s1_connection_accept_fn(qb_ipcs_connection_t *c, uid_t uid, gid_t gid)
#endif
}
static void
s1_connection_created_fn(qb_ipcs_connection_t *c)
static void
s1_connection_created_fn(qb_ipcs_connection_t * c)
{
struct qb_ipcs_stats srv_stats;
qb_ipcs_stats_get(s1, &srv_stats, QB_FALSE);
qb_log(LOG_INFO, "Connection created (active:%d, closed:%d)",
srv_stats.active_connections,
srv_stats.closed_connections);
srv_stats.active_connections, srv_stats.closed_connections);
}
static void
s1_connection_destroyed_fn(qb_ipcs_connection_t *c)
static void
s1_connection_destroyed_fn(qb_ipcs_connection_t * c)
{
qb_log(LOG_INFO, "Connection about to be freed");
}
static int32_t
s1_connection_closed_fn(qb_ipcs_connection_t *c)
static int32_t
s1_connection_closed_fn(qb_ipcs_connection_t * c)
{
struct qb_ipcs_connection_stats stats;
struct qb_ipcs_stats srv_stats;
qb_ipcs_stats_get(s1, &srv_stats, QB_FALSE);
qb_ipcs_connection_stats_get(c, &stats, QB_FALSE);
qb_log(LOG_INFO, "Connection to pid:%d destroyed (active:%d, closed:%d)",
stats.client_pid,
srv_stats.active_connections,
qb_log(LOG_INFO,
"Connection to pid:%d destroyed (active:%d, closed:%d)",
stats.client_pid, srv_stats.active_connections,
srv_stats.closed_connections);
qb_log(LOG_DEBUG, " Requests %"PRIu64"", stats.requests);
@ -92,36 +92,69 @@ s1_connection_closed_fn(qb_ipcs_connection_t *c)
return 0;
}
static int32_t
s1_msg_process_fn(qb_ipcs_connection_t *c,
void *data, size_t size)
struct my_req {
struct qb_ipc_request_header hdr;
char message[256];
};
static int32_t
s1_msg_process_fn(qb_ipcs_connection_t * c, void *data, size_t size)
{
struct qb_ipc_request_header *req_pt = (struct qb_ipc_request_header *)data;
struct qb_ipc_request_header *hdr;
struct my_req *req_pt;
struct qb_ipc_response_header response;
ssize_t res;
struct iovec iov[2];
char resp[100];
int32_t sl;
int32_t send_ten_events = QB_FALSE;
qb_log(LOG_DEBUG, "msg received (id:%d, size:%d)",
req_pt->id, req_pt->size);
hdr = (struct qb_ipc_request_header *)data;
if (hdr->id == (QB_IPC_MSG_USER_START + 1)) {
return 0;
}
req_pt = (struct my_req *)data;
qb_log(LOG_DEBUG, "msg received (id:%d, size:%d, data:%s)",
req_pt->hdr.id, req_pt->hdr.size, req_pt->message);
if (strcmp(req_pt->message, "kill") == 0) {
exit(0);
}
response.size = sizeof(struct qb_ipc_response_header);
response.id = 13;
response.error = 0;
snprintf(resp, 100, "ACK %zd bytes", size);
sl = snprintf(resp, 100, "ACK %zd bytes", size) + 1;
iov[0].iov_len = sizeof(response);
iov[0].iov_base = &response;
iov[1].iov_len = strlen(resp) + 1;
iov[1].iov_len = sl;
iov[1].iov_base = resp;
response.size += sl;
res = qb_ipcs_response_sendv(c, iov, 2);
send_ten_events = (strcmp(req_pt->message, "events") == 0);
if (use_events && !send_ten_events) {
res = qb_ipcs_event_sendv(c, iov, 2);
} else {
res = qb_ipcs_response_sendv(c, iov, 2);
}
if (res < 0) {
errno = - res;
qb_perror(LOG_ERR, "qb_ipcs_response_send");
}
if (send_ten_events) {
int32_t i;
qb_log(LOG_INFO, "request to send 10 events");
for (i = 0; i < 10; i++) {
res = qb_ipcs_event_sendv(c, iov, 2);
qb_log(LOG_INFO, "sent event %d res:%d", i, res);
}
}
return 0;
}
static void
static void
sigusr1_handler(int32_t num)
{
qb_log(LOG_DEBUG, "(%d)", num);
@ -129,7 +162,7 @@ sigusr1_handler(int32_t num)
exit(0);
}
static void
static void
show_usage(const char *name)
{
printf("usage: \n");
@ -139,10 +172,9 @@ show_usage(const char *name)
printf("\n");
printf(" -h show this help text\n");
printf(" -m use shared memory\n");
printf(" -p use posix message queues\n");
printf(" -s use sysv message queues\n");
printf(" -u use unix sockets\n");
printf(" -g use glib mainloop\n");
printf(" -e use events\n");
printf("\n");
}
@ -151,13 +183,13 @@ struct gio_to_qb_poll {
gboolean is_used;
GIOChannel *channel;
int32_t events;
void * data;
void *data;
qb_ipcs_dispatch_fn_t fn;
enum qb_loop_priority p;
};
static gboolean
gio_read_socket (GIOChannel *gio, GIOCondition condition, gpointer data)
gio_read_socket(GIOChannel * gio, GIOCondition condition, gpointer data)
{
struct gio_to_qb_poll *adaptor = (struct gio_to_qb_poll *)data;
gint fd = g_io_channel_unix_get_fd(gio);
@ -165,15 +197,15 @@ gio_read_socket (GIOChannel *gio, GIOCondition condition, gpointer data)
return (adaptor->fn(fd, condition, adaptor->data) == 0);
}
static int32_t
static int32_t
my_g_dispatch_add(enum qb_loop_priority p, int32_t fd, int32_t evts,
void *data, qb_ipcs_dispatch_fn_t fn)
void *data, qb_ipcs_dispatch_fn_t fn)
{
struct gio_to_qb_poll *adaptor;
GIOChannel *channel;
int32_t res = 0;
res = qb_array_index(gio_map, fd, (void**)&adaptor);
res = qb_array_index(gio_map, fd, (void **)&adaptor);
if (res < 0) {
return res;
}
@ -199,7 +231,7 @@ my_g_dispatch_add(enum qb_loop_priority p, int32_t fd, int32_t evts,
static int32_t
my_g_dispatch_mod(enum qb_loop_priority p, int32_t fd, int32_t evts,
void *data, qb_ipcs_dispatch_fn_t fn)
void *data, qb_ipcs_dispatch_fn_t fn)
{
return 0;
}
@ -208,7 +240,7 @@ static int32_t
my_g_dispatch_del(int32_t fd)
{
struct gio_to_qb_poll *adaptor;
if (qb_array_index(gio_map, fd, (void**)&adaptor) == 0) {
if (qb_array_index(gio_map, fd, (void **)&adaptor) == 0) {
g_io_channel_unref(adaptor->channel);
adaptor->is_used = FALSE;
}
@ -216,7 +248,7 @@ my_g_dispatch_del(int32_t fd)
}
#endif /* HAVE_GLIB */
static int32_t
static int32_t
my_job_add(enum qb_loop_priority p, void *data, qb_loop_job_dispatch_fn fn)
{
return qb_loop_job_add(bms_loop, p, data, fn);
@ -224,14 +256,14 @@ my_job_add(enum qb_loop_priority p, void *data, qb_loop_job_dispatch_fn fn)
static int32_t
my_dispatch_add(enum qb_loop_priority p, int32_t fd, int32_t evts,
void *data, qb_ipcs_dispatch_fn_t fn)
void *data, qb_ipcs_dispatch_fn_t fn)
{
return qb_loop_poll_add(bms_loop, p, fd, evts, data, fn);
}
static int32_t
static int32_t
my_dispatch_mod(enum qb_loop_priority p, int32_t fd, int32_t evts,
void *data, qb_ipcs_dispatch_fn_t fn)
void *data, qb_ipcs_dispatch_fn_t fn)
{
return qb_loop_poll_mod(bms_loop, p, fd, evts, data, fn);
}
@ -245,9 +277,9 @@ my_dispatch_del(int32_t fd)
int32_t
main(int32_t argc, char *argv[])
{
const char *options = "mpsugh";
const char *options = "mpseugh";
int32_t opt;
enum qb_ipc_type ipc_type = QB_IPC_SHM;
enum qb_ipc_type ipc_type = QB_IPC_NATIVE;
struct qb_ipcs_service_handlers sh = {
.connection_accept = s1_connection_accept_fn,
.connection_created = s1_connection_created_fn,
@ -275,18 +307,15 @@ main(int32_t argc, char *argv[])
case 'm':
ipc_type = QB_IPC_SHM;
break;
case 's':
ipc_type = QB_IPC_SYSV_MQ;
break;
case 'u':
ipc_type = QB_IPC_SOCKET;
break;
case 'p':
ipc_type = QB_IPC_POSIX_MQ;
break;
case 'g':
use_glib = QB_TRUE;
break;
case 'e':
use_events = QB_TRUE;
break;
case 'h':
default:
show_usage(argv[0]);
@ -296,10 +325,9 @@ main(int32_t argc, char *argv[])
}
signal(SIGINT, sigusr1_handler);
qb_log_init("ipcserver", LOG_USER, LOG_WARNING);
qb_log_init("ipcserver", LOG_USER, LOG_TRACE);
qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, __FILE__,
LOG_DEBUG);
QB_LOG_FILTER_FILE, "*", LOG_TRACE);
qb_log_format_set(QB_LOG_STDERR, "%f:%l [%p] %b");
qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
@ -321,7 +349,8 @@ main(int32_t argc, char *argv[])
qb_ipcs_run(s1);
g_main_loop_run(glib_loop);
#else
qb_log(LOG_ERR, "You don't seem to have glib-devel installed.\n");
qb_log(LOG_ERR,
"You don't seem to have glib-devel installed.\n");
#endif
}
return EXIT_SUCCESS;

View File

@ -26,7 +26,8 @@
#include <qb/qbmap.h>
static void
notify_fn(uint32_t event, char* key, void* old_value, void* value, void* user_data)
notify_fn(uint32_t event, char *key, void *old_value, void *value,
void *user_data)
{
if (event == QB_MAP_NOTIFY_FREE) {
fprintf(stderr, "Notify[FREE] %s [%d]\n",
@ -44,13 +45,14 @@ notify_fn(uint32_t event, char* key, void* old_value, void* value, void* user_da
fprintf(stderr, " value = [%d]\n", *(int *)value);
}
if (old_value != NULL) {
fprintf(stderr, " old value = [%d]\n", *(int *)old_value);
fprintf(stderr, " old value = [%d]\n",
*(int *)old_value);
}
}
}
static void
add_cs_keys(qb_map_t *m)
add_cs_keys(qb_map_t * m)
{
qb_map_put(m, "compatibility", strdup("none"));
qb_map_put(m, "totem.version", strdup("2"));
@ -197,7 +199,7 @@ main(void)
iter = qb_map_pref_iter_create(trie, "test.");
while ((key = qb_map_iter_next(iter, &val)) != NULL) {
fprintf(stderr,"Iter %s [%d]\n", key, *(int*)val);
fprintf(stderr, "Iter %s [%d]\n", key, *(int *)val);
qb_map_rm(trie, key);
}
qb_map_iter_free(iter);

View File

@ -29,18 +29,19 @@
#define MY_TAG_TWO (1 << 1)
#define MY_TAG_THREE (1 << 2)
static int32_t _log_priority = LOG_WARNING;
static uint8_t _log_priority = LOG_WARNING;
static void func_one(void)
static void
func_one(void)
{
FILE* fd;
FILE *fd;
qb_enter();
qb_logt(LOG_DEBUG, MY_TAG_TWO, "arf arf?");
qb_logt(LOG_CRIT, MY_TAG_THREE, "arrrg!");
qb_logt(134, MY_TAG_THREE, "big priority");
qb_logt(LOG_ERR, MY_TAG_THREE, "oops, I did it again");
qb_log(LOG_INFO, "are you aware ...");
qb_logt(LOG_CRIT, MY_TAG_THREE, "arrrg!");
qb_logt(134, MY_TAG_THREE, "big priority");
qb_logt(LOG_ERR, MY_TAG_THREE, "oops, I did it again");
qb_log(LOG_INFO, "are you aware ...");
fd = fopen("/nothing.txt", "r+");
if (fd == NULL) {
@ -51,17 +52,19 @@ static void func_one(void)
qb_leave();
}
static void func_two(void)
static void
func_two(void)
{
qb_enter();
qb_logt(LOG_DEBUG, 0, "arf arf?");
qb_logt(LOG_CRIT, MY_TAG_ONE, "arrrg!");
qb_log(LOG_ERR, "oops, I did it again");
qb_logt(LOG_INFO, MY_TAG_THREE, "are you aware ...");
qb_logt(LOG_CRIT, MY_TAG_ONE, "arrrg!");
qb_log(LOG_ERR, "oops, I did it again");
qb_logt(LOG_INFO, MY_TAG_THREE, "are you aware ...");
qb_leave();
}
static void show_usage(const char *name)
static void
show_usage(const char *name)
{
printf("usage: \n");
printf("%s <options>\n", name);
@ -80,9 +83,10 @@ static void show_usage(const char *name)
static int32_t do_blackbox = QB_FALSE;
static int32_t do_threaded = QB_FALSE;
static void sigsegv_handler(int sig)
static void
sigsegv_handler(int sig)
{
(void)signal (SIGSEGV, SIG_DFL);
(void)signal(SIGSEGV, SIG_DFL);
qb_log_fini();
if (do_blackbox) {
qb_log_blackbox_write_to_file("simple-log.fdata");
@ -90,7 +94,8 @@ static void sigsegv_handler(int sig)
raise(SIGSEGV);
}
static const char *my_tags_stringify(uint32_t tags)
static const char *
my_tags_stringify(uint32_t tags)
{
if (qb_bit_is_set(tags, QB_LOG_TAG_LIBQB_MSG_BIT)) {
return "libqb";
@ -107,9 +112,7 @@ static const char *my_tags_stringify(uint32_t tags)
static void
trace_logger(int32_t t,
struct qb_log_callsite *cs,
time_t timestamp,
const char *msg)
struct qb_log_callsite *cs, time_t timestamp, const char *msg)
{
char output_buffer[QB_LOG_MAX_LEN];
output_buffer[0] = '\0';
@ -122,14 +125,15 @@ m_filter(struct qb_log_callsite *cs)
{
if ((cs->priority >= LOG_ALERT &&
cs->priority <= _log_priority) &&
strcmp(cs->filename, __FILE__) == 0) {
strcmp(cs->filename, __FILE__) == 0) {
qb_bit_set(cs->targets, QB_LOG_STDERR);
} else {
qb_bit_clear(cs->targets, QB_LOG_STDERR);
}
}
int32_t main(int32_t argc, char *argv[])
int32_t
main(int32_t argc, char *argv[])
{
const char *options = "vhteobdf:";
int32_t opt;
@ -182,7 +186,6 @@ int32_t main(int32_t argc, char *argv[])
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_THREADED, do_threaded);
qb_log_tags_stringify_fn_set(my_tags_stringify);
if (do_stderr) {
qb_log_filter_fn_set(m_filter);
qb_log_format_set(QB_LOG_STDERR, "[%p] %4g: %f:%l %b");
@ -223,13 +226,25 @@ int32_t main(int32_t argc, char *argv[])
qb_log(LOG_DEBUG, "hello");
qb_log(LOG_INFO, "this is an info");
qb_log(LOG_NOTICE, "hello - notice?");
{
char * str = NULL;
qb_log(LOG_ERR,
"%s-%d-%s-%u",
NULL, 952, str, 56);
}
func_one();
func_two();
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
if (!do_threaded) {
/* Disabling syslog here will prevent the logs from
* getting flushed in qb_log_fini() if threaded
* logging is on.
*/
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
qb_log(LOG_WARNING, "no syslog");
qb_log(LOG_ERR, "no syslog");
qb_log(LOG_WARNING, "no syslog");
qb_log(LOG_ERR, "no syslog");
}
#if 0
// test blackbox
@ -240,8 +255,8 @@ int32_t main(int32_t argc, char *argv[])
qb_log_blackbox_write_to_file("simple-log.fdata");
qb_log_blackbox_print_from_file("simple-log.fdata");
qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
unlink("simple-log.fdata");
}
qb_log_fini();
return 0;
}

View File

@ -19,8 +19,19 @@
* along with libqb. If not, see <http://www.gnu.org/licenses/>.
*/
#include "os_base.h"
#include <netdb.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif /* HAVE_ARPA_INET_H */
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif /* HAVE_NETDB_H */
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif /* HAVE_SYS_SOCKET_H */
int
main(int argc, char *argv[])
@ -40,8 +51,9 @@ main(int argc, char *argv[])
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(5000);
memcpy(&server_addr.sin_addr, host->h_addr_list[0], sizeof(server_addr.sin_addr));
bzero(&(server_addr.sin_zero),8);
memcpy(&server_addr.sin_addr, host->h_addr_list[0],
sizeof(server_addr.sin_addr));
bzero(&(server_addr.sin_zero), 8);
if (connect(sock, (struct sockaddr *)&server_addr,
sizeof(struct sockaddr)) == -1) {
@ -49,7 +61,7 @@ main(int argc, char *argv[])
exit(1);
}
while(1) {
while (1) {
printf("\nSEND (q or Q to quit) : ");
if (fgets(send_data, 1024, stdin) == NULL) {
continue;

View File

@ -20,9 +20,21 @@
*/
#include "os_base.h"
#include <netdb.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif /* HAVE_NETINET_IN_H */
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#include <poll.h>
#endif /* HAVE_ARPA_INET_H */
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif /* HAVE_NETDB_H */
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif /* HAVE_SYS_SOCKET_H */
#ifdef HAVE_SYS_POLL_H
#include <sys/poll.h>
#endif /* HAVE_SYS_POLL_H */
#include <qb/qbdefs.h>
#include <qb/qbloop.h>
@ -47,8 +59,7 @@ sock_read_fn(int32_t fd, int32_t revents, void *data)
}
recv_data[bytes_recieved] = '\0';
if (strcmp(recv_data, "q") == 0 ||
strcmp(recv_data, "Q") == 0) {
if (strcmp(recv_data, "q") == 0 || strcmp(recv_data, "Q") == 0) {
printf("Quiting connection from socket %d\n", fd);
close(fd);
return QB_FALSE;
@ -64,7 +75,7 @@ static int32_t
sock_accept_fn(int32_t fd, int32_t revents, void *data)
{
struct sockaddr_in client_addr;
qb_loop_t * ml = (qb_loop_t*)data;
qb_loop_t *ml = (qb_loop_t *) data;
socklen_t sin_size = sizeof(struct sockaddr_in);
int connected = accept(fd, (struct sockaddr *)&client_addr, &sin_size);
@ -73,12 +84,9 @@ sock_accept_fn(int32_t fd, int32_t revents, void *data)
return QB_TRUE;
}
printf("I got a connection from (%s , %d)\n",
inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
qb_loop_poll_add(ml, QB_LOOP_MED,
connected, POLLIN,
ml, sock_read_fn);
qb_loop_poll_add(ml, QB_LOOP_MED, connected, POLLIN, ml, sock_read_fn);
return QB_TRUE;
}
@ -86,7 +94,7 @@ sock_accept_fn(int32_t fd, int32_t revents, void *data)
static int32_t
please_exit_fn(int32_t rsignal, void *data)
{
qb_loop_t * ml = (qb_loop_t*)data;
qb_loop_t *ml = (qb_loop_t *) data;
printf("Shutting down at you request...\n");
qb_loop_stop(ml);
@ -99,20 +107,16 @@ main(int argc, char *argv[])
int sock;
int true_opt = 1;
struct sockaddr_in server_addr;
qb_loop_t * ml = qb_loop_create();
qb_loop_t *ml = qb_loop_create();
if ((sock = socket(AF_INET,
SOCK_STREAM,
0)) == -1) {
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Socket");
exit(1);
}
if (setsockopt(sock,
SOL_SOCKET,
SO_REUSEADDR,
&true_opt,
sizeof(int)) == -1) {
SO_REUSEADDR, &true_opt, sizeof(int)) == -1) {
perror("Setsockopt");
exit(1);
}
@ -120,7 +124,7 @@ main(int argc, char *argv[])
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(5000);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero),8);
bzero(&(server_addr.sin_zero), 8);
printf("TCPServer binding to port 5000\n");
if (bind(sock,
@ -137,14 +141,9 @@ main(int argc, char *argv[])
exit(1);
}
qb_loop_poll_add(ml, QB_LOOP_MED,
sock, POLLIN,
ml, sock_accept_fn);
qb_loop_poll_add(ml, QB_LOOP_MED, sock, POLLIN, ml, sock_accept_fn);
qb_loop_signal_add(ml, QB_LOOP_HIGH,
SIGINT,
ml, please_exit_fn,
NULL);
qb_loop_signal_add(ml, QB_LOOP_HIGH, SIGINT, ml, please_exit_fn, NULL);
qb_loop_run(ml);
close(sock);

View File

@ -164,7 +164,6 @@ LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIB_RT = @LIB_RT@
LINT_FLAGS = @LINT_FLAGS@
LIPO = @LIPO@
LN_S = @LN_S@

View File

@ -6,6 +6,9 @@
/* Compiling Debugging code */
#undef DEBUG
/* Disable shared mem ipc */
#undef DISABLE_IPC_SHM
/* Disable _POSIX_THREAD_PROCESS_SHARED */
#undef DISABLE_POSIX_THREAD_PROCESS_SHARED
@ -21,6 +24,10 @@
/* Define to 1 if you have the `clock_gettime' function. */
#undef HAVE_CLOCK_GETTIME
/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
don't. */
#undef HAVE_DECL_STRERROR_R
/* "Have /usr/share/dict/words" */
#undef HAVE_DICT_WORDS
@ -51,6 +58,12 @@
/* Define to 1 if you have the `getpagesize' function. */
#undef HAVE_GETPAGESIZE
/* Define to 1 if you have the `getpeereid' function. */
#undef HAVE_GETPEEREID
/* Define to 1 if you have the `getpeerucred' function. */
#undef HAVE_GETPEERUCRED
/* Define to 1 if you have the `getrlimit' function. */
#undef HAVE_GETRLIMIT
@ -63,17 +76,8 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `dl' library (-ldl). */
#undef HAVE_LIBDL
/* Define to 1 if you have the `pthread' library (-lpthread). */
#undef HAVE_LIBPTHREAD
/* Define to 1 if you have the `rt' library (-lrt). */
#undef HAVE_LIBRT
/* Define to 1 if you have the `socket' library (-lsocket). */
#undef HAVE_LIBSOCKET
/* Define to 1 if you have the `kqueue' function. */
#undef HAVE_KQUEUE
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
@ -96,20 +100,23 @@
/* Define to 1 if you have a working `mmap' system call. */
#undef HAVE_MMAP
/* Define to 1 if you have the <mqueue.h> header file. */
#undef HAVE_MQUEUE_H
/* Define to 1 if you have the `munmap' function. */
#undef HAVE_MUNMAP
/* Define to 1 if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
/* Define to 1 if you have the `poll' function. */
#undef HAVE_POLL
/* have posix message queues */
#undef HAVE_POSIX_MQ
/* Define to 1 if you have the `pthread_condattr_setpshared' function. */
#undef HAVE_PTHREAD_CONDATTR_SETPSHARED
/* Define to 1 if you have the `pthread_mutexattr_setpshared' function. */
#undef HAVE_PTHREAD_MUTEXATTR_SETPSHARED
/* Define to 1 if you have the `pthread_setschedparam' function. */
#undef HAVE_PTHREAD_SETSCHEDPARAM
@ -129,18 +136,33 @@
/* Define to 1 if you have the `sched_setscheduler' function. */
#undef HAVE_SCHED_SETSCHEDULER
/* Define to 1 if you have the `semtimedop' function. */
#undef HAVE_SEMTIMEDOP
/* Define to 1 if you have union semun. */
#undef HAVE_SEMUN
/* Define to 1 if you have the `sem_timedwait' function. */
#undef HAVE_SEM_TIMEDWAIT
/* have slow tests */
#undef HAVE_SLOW_TESTS
/* Define to 1 if you have the `socket' function. */
#undef HAVE_SOCKET
/* Define to 1 if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strcasecmp' function. */
#undef HAVE_STRCASECMP
/* Define to 1 if you have the `strchr' function. */
#undef HAVE_STRCHR
@ -150,8 +172,8 @@
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the `strerror_r' function. */
#undef HAVE_STRERROR_R
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
@ -171,18 +193,21 @@
/* Define to 1 if you have the `strstr' function. */
#undef HAVE_STRSTR
/* Define to 1 if struct sockaddr_un has a member sun_len */
#undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
/* Define to 1 if you have the `sysconf' function. */
#undef HAVE_SYSCONF
/* Define to 1 if you have the <syslog.h> header file. */
#undef HAVE_SYSLOG_H
/* have sysv message queues */
#undef HAVE_SYSV_MQ
/* Define to 1 if you have the <sys/epoll.h> header file. */
#undef HAVE_SYS_EPOLL_H
/* Define to 1 if you have the <sys/event.h> header file. */
#undef HAVE_SYS_EVENT_H
/* Define to 1 if you have the <sys/ipc.h> header file. */
#undef HAVE_SYS_IPC_H
@ -253,12 +278,6 @@
*/
#undef LT_OBJDIR
/* Shared memory define for Darwin platform */
#undef MAP_ANONYMOUS
/* Number of chars in a file name */
#undef NAME_MAX
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
#undef NO_MINUS_C_MINUS_O
@ -286,9 +305,6 @@
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Number of chars in a path name including nul */
#undef PATH_MAX
/* alpha */
#undef QB_ARCH_ALPHA
@ -313,6 +329,9 @@
/* Compiling for BSD platform */
#undef QB_BSD
/* Compiling for Cygwin platform */
#undef QB_CYGWIN
/* Compiling for Darwin platform */
#undef QB_DARWIN
@ -337,14 +356,46 @@
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Prevent being scheduled RR */
#undef TS_CLASS
/* Define to 1 if strerror_r returns char *. */
#undef STRERROR_R_CHAR_P
/* Unix path length */
#undef UNIX_PATH_MAX
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
#endif
/* Version number of package */
#undef VERSION
/* The semun structure is undefined */
#undef _SEM_SEMUN_UNDEFINED
/* Define to 1 if on MINIX. */
#undef _MINIX
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
#undef _POSIX_1_SOURCE
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
@ -397,6 +448,10 @@
/* Define to `int' if <sys/types.h> doesn't define. */
#undef uid_t
/* Define to the type of an unsigned integer type of width exactly 16 bits if
such a type exists and the standard includes do not define it. */
#undef uint16_t
/* Define to the type of an unsigned integer type of width exactly 32 bits if
such a type exists and the standard includes do not define it. */
#undef uint32_t

View File

@ -25,10 +25,6 @@
#include <config.h>
#endif /* HAVE_CONFIG_H */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif /* _GNU_SOURCE */
#include <stdio.h>
#include <stdarg.h>
#include <limits.h>
@ -45,6 +41,10 @@
#include <stdint.h>
#endif /* HAVE_STDINT_H */
#ifdef HAVE_STDDEF_H
#include <stddef.h>
#endif /* HAVE_STDDEF_H */
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
@ -107,24 +107,55 @@
#define HAVE_EPOLL 1
#endif /* HAVE_EPOLL_CREATE */
/*
* Darwin claims to support process shared synchronization
* but it really does not. The unistd.h header file is wrong.
#if defined(__UCLIBC__)
#define DISABLE_POSIX_THREAD_PROCESS_SHARED 1
#endif
/* The pshared semaphore madness:
* To have a usable pshared semaphore we need the timed_wait api
* and pshared functionality.
*
* The order of choice is:
* 1) real posix sem -> HAVE_POSIX_PSHARED_SEMAPHORE
* 2) sysv sems (if we have semtimedop) -> HAVE_SYSV_PSHARED_SEMAPHORE
* 3) faked sems using pthread_cond_timedwait -> HAVE_RPL_PSHARED_SEMAPHORE
* 4) ENOTSUP
*/
#if defined(DISABLE_POSIX_THREAD_PROCESS_SHARED) || defined(__UCLIBC__)
#undef HAVE_POSIX_SHARED_SEMAPHORE
#undef HAVE_PTHREAD_SHARED_SPIN_LOCK
#else
#if _POSIX_THREAD_PROCESS_SHARED > 0
#define HAVE_POSIX_SHARED_SEMAPHORE 1
#undef HAVE_POSIX_PSHARED_SEMAPHORE
#undef HAVE_SYSV_PSHARED_SEMAPHORE
#undef HAVE_RPL_PSHARED_SEMAPHORE
#if defined(HAVE_PTHREAD_SPIN_LOCK)
#define HAVE_PTHREAD_SHARED_SPIN_LOCK 1
#endif /* HAVE_PTHREAD_SPIN_LOCK */
#endif /* _POSIX_THREAD_PROCESS_SHARED */
#if defined(DISABLE_POSIX_THREAD_PROCESS_SHARED)
#undef HAVE_PTHREAD_SHARED_SPIN_LOCK
#endif /* DISABLE_POSIX_THREAD_PROCESS_SHARED */
#if !defined(DISABLE_POSIX_THREAD_PROCESS_SHARED) && \
_POSIX_THREAD_PROCESS_SHARED > 0
#if defined(HAVE_PTHREAD_SPIN_LOCK)
#define HAVE_PTHREAD_SHARED_SPIN_LOCK 1
#endif /* HAVE_PTHREAD_SPIN_LOCK */
#if defined(HAVE_SEM_TIMEDWAIT)
#define HAVE_POSIX_PSHARED_SEMAPHORE 1
#else
#if defined(HAVE_PTHREAD_CONDATTR_SETPSHARED) && \
defined(HAVE_PTHREAD_MUTEXATTR_SETPSHARED)
#define HAVE_RPL_PSHARED_SEMAPHORE 1
#endif
#endif /* HAVE_SEM_TIMEDWAIT */
#endif /* posix pshared */
#ifdef HAVE_SEMTIMEDOP
#define HAVE_SYSV_PSHARED_SEMAPHORE 1
#endif /* HAVE_SEM_TIMEDWAIT */
#if !defined(HAVE_SYSV_PSHARED_SEMAPHORE) && \
!defined(HAVE_POSIX_PSHARED_SEMAPHORE) && \
!defined(HAVE_RPL_PSHARED_SEMAPHORE)
#define DISABLE_IPC_SHM 1
#endif /* HAVE PSHARED SEMAPHORE */
#ifndef HAVE_STRCHRNUL
char *strchrnul (const char *s, int c_in);
#endif
@ -137,4 +168,11 @@ size_t strlcpy(char *dest, const char *src, size_t maxlen);
size_t strlcat(char *dest, const char *src, size_t maxlen);
#endif
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#ifndef NAME_MAX
#define NAME_MAX 255
#endif
#endif /* QB_OS_BASE_H_DEFINED */

View File

@ -154,7 +154,6 @@ LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIB_RT = @LIB_RT@
LINT_FLAGS = @LINT_FLAGS@
LIPO = @LIPO@
LN_S = @LN_S@

View File

@ -47,6 +47,7 @@ enum qb_ipc_type {
QB_IPC_SHM,
QB_IPC_POSIX_MQ,
QB_IPC_SYSV_MQ,
QB_IPC_NATIVE,
};

View File

@ -106,6 +106,10 @@ int32_t qb_ipcc_fc_enable_max_set(qb_ipcc_connection_t * c, uint32_t max);
* @param msg_ptr pointer to a message to send
* @param msg_len the size of the message
* @return (size sent, -errno == error)
*
* @note the msg_ptr must include a qb_ipc_request_header at
* the top of the message. The server will read the size field
* to determine how much to recv.
*/
ssize_t qb_ipcc_send(qb_ipcc_connection_t* c, const void *msg_ptr,
size_t msg_len);
@ -116,6 +120,9 @@ ssize_t qb_ipcc_send(qb_ipcc_connection_t* c, const void *msg_ptr,
* @param iov pointer to an iovec struct to send
* @param iov_len the number of iovecs used
* @return (size sent, -errno == error)
*
* @note the iov[0] must be a qb_ipc_request_header. The server will
* read the size field to determine how much to recv.
*/
ssize_t qb_ipcc_sendv(qb_ipcc_connection_t* c, const struct iovec* iov,
size_t iov_len);
@ -127,6 +134,9 @@ ssize_t qb_ipcc_sendv(qb_ipcc_connection_t* c, const struct iovec* iov,
* @param msg_len the size of the buffer
* @param ms_timeout max time to wait for a response
* @return (size recv'ed, -errno == error)
*
* @note that msg_ptr will include a qb_ipc_response_header at
* the top of the message.
*/
ssize_t qb_ipcc_recv(qb_ipcc_connection_t* c, void *msg_ptr,
size_t msg_len, int32_t ms_timeout);
@ -141,6 +151,12 @@ ssize_t qb_ipcc_recv(qb_ipcc_connection_t* c, void *msg_ptr,
* @param msg_len the size of the buffer
* @param ms_timeout max time to wait for a response
*
* @note the iov[0] must include a qb_ipc_request_header at
* the top of the message. The server will read the size field
* to determine how much to recv.
* @note that msg_ptr will include a qb_ipc_response_header at
* the top of the message.
*
* @see qb_ipcc_sendv() qb_ipcc_recv()
*/
ssize_t qb_ipcc_sendv_recv(qb_ipcc_connection_t *c,
@ -158,6 +174,9 @@ ssize_t qb_ipcc_sendv_recv(qb_ipcc_connection_t *c,
* 0 == no wait, negative == block, positive == wait X ms.
* @param ms_timeout max time to wait for a response
* @return size of the message or error (-errno)
*
* @note that msg_ptr will include a qb_ipc_response_header at
* the top of the message.
*/
ssize_t qb_ipcc_event_recv(qb_ipcc_connection_t* c, void *msg_ptr,
size_t msg_len, int32_t ms_timeout);
@ -180,6 +199,14 @@ void qb_ipcc_context_set(qb_ipcc_connection_t *c, void *context);
*/
void *qb_ipcc_context_get(qb_ipcc_connection_t *c);
/**
* Is the connection connected?
*
* @param c connection instance
* @retval QB_TRUE when connected
* @retval QB_FALSE when not connected
*/
int32_t qb_ipcc_is_connected(qb_ipcc_connection_t *c);
/* *INDENT-OFF* */
#ifdef __cplusplus

View File

@ -73,6 +73,18 @@ struct qb_ipcs_connection_stats {
uint64_t flow_control_count;
};
struct qb_ipcs_connection_stats_2 {
int32_t client_pid;
uint64_t requests;
uint64_t responses;
uint64_t events;
uint64_t send_retries;
uint64_t recv_retries;
int32_t flow_control_state;
uint64_t flow_control_count;
uint32_t event_q_length;
};
typedef int32_t (*qb_ipcs_dispatch_fn_t) (int32_t fd, int32_t revents,
void *data);
@ -105,8 +117,11 @@ struct qb_ipcs_poll_handlers {
* The type of checks you should do are authentication, service availabilty
* or process resource constraints.
* @return 0 to accept or -errno to indicate a failure (sent back to the client)
*
* @note you can call qb_ipcs_connection_auth_set() within this function.
*/
typedef int32_t (*qb_ipcs_connection_accept_fn) (qb_ipcs_connection_t *c, uid_t uid, gid_t gid);
typedef int32_t (*qb_ipcs_connection_accept_fn) (qb_ipcs_connection_t *c,
uid_t uid, gid_t gid);
/**
* This is called after a new connection has been created.
@ -198,7 +213,8 @@ void qb_ipcs_destroy(qb_ipcs_service_t* s);
* @param s service instance
* @param rl the new rate
*/
void qb_ipcs_request_rate_limit(qb_ipcs_service_t* s, enum qb_ipcs_rate_limit rl);
void qb_ipcs_request_rate_limit(qb_ipcs_service_t* s,
enum qb_ipcs_rate_limit rl);
/**
* Send a response to a incomming request.
@ -207,8 +223,13 @@ void qb_ipcs_request_rate_limit(qb_ipcs_service_t* s, enum qb_ipcs_rate_limit rl
* @param data the message to send
* @param size the size of the message
* @return size sent or -errno for errors
*
* @note the data must include a qb_ipc_response_header at
* the top of the message. The client will read the size field
* to determine how much to recv.
*/
ssize_t qb_ipcs_response_send(qb_ipcs_connection_t *c, const void *data, size_t size);
ssize_t qb_ipcs_response_send(qb_ipcs_connection_t *c, const void *data,
size_t size);
/**
* Send a response to a incomming request.
@ -217,8 +238,12 @@ ssize_t qb_ipcs_response_send(qb_ipcs_connection_t *c, const void *data, size_t
* @param iov the iovec struct that points to the message to send
* @param iov_len the number of iovecs.
* @return size sent or -errno for errors
*
* @note the iov[0] must be a qb_ipc_response_header. The client will
* read the size field to determine how much to recv.
*/
ssize_t qb_ipcs_response_sendv(qb_ipcs_connection_t *c, const struct iovec * iov, size_t iov_len);
ssize_t qb_ipcs_response_sendv(qb_ipcs_connection_t *c,
const struct iovec * iov, size_t iov_len);
/**
* Send an asyncronous event message to the client.
@ -227,8 +252,13 @@ ssize_t qb_ipcs_response_sendv(qb_ipcs_connection_t *c, const struct iovec * iov
* @param data the message to send
* @param size the size of the message
* @return size sent or -errno for errors
*
* @note the data must include a qb_ipc_response_header at
* the top of the message. The client will read the size field
* to determine how much to recv.
*/
ssize_t qb_ipcs_event_send(qb_ipcs_connection_t *c, const void *data, size_t size);
ssize_t qb_ipcs_event_send(qb_ipcs_connection_t *c, const void *data,
size_t size);
/**
* Send an asyncronous event message to the client.
@ -237,8 +267,12 @@ ssize_t qb_ipcs_event_send(qb_ipcs_connection_t *c, const void *data, size_t siz
* @param iov the iovec struct that points to the message to send
* @param iov_len the number of iovecs.
* @return size sent or -errno for errors
*
* @note the iov[0] must be a qb_ipc_response_header. The client will
* read the size field to determine how much to recv.
*/
ssize_t qb_ipcs_event_sendv(qb_ipcs_connection_t *c, const struct iovec * iov, size_t iov_len);
ssize_t qb_ipcs_event_sendv(qb_ipcs_connection_t *c, const struct iovec * iov,
size_t iov_len);
/**
* Increment the connection's reference counter.
@ -290,6 +324,7 @@ void *qb_ipcs_context_get(qb_ipcs_connection_t *c);
/**
* Get the connection statistics.
*
* @deprecated from v0.13.0 onwards, use qb_ipcs_connection_stats_get_2
* @param stats (out) the statistics structure
* @param clear_after_read clear stats after copying them into stats
* @param c connection instance
@ -298,6 +333,17 @@ void *qb_ipcs_context_get(qb_ipcs_connection_t *c);
int32_t qb_ipcs_connection_stats_get(qb_ipcs_connection_t *c,
struct qb_ipcs_connection_stats* stats,
int32_t clear_after_read);
/**
* Get (and allocate) the connection statistics.
*
* @param clear_after_read clear stats after copying them into stats
* @param c connection instance
* @retval NULL if no memory or invalid connection
* @retval allocated statistics structure (user must free it).
*/
struct qb_ipcs_connection_stats_2*
qb_ipcs_connection_stats_get_2(qb_ipcs_connection_t *c,
int32_t clear_after_read);
/**
* Get the service statistics.
@ -333,6 +379,23 @@ qb_ipcs_connection_t * qb_ipcs_connection_first_get(qb_ipcs_service_t* pt);
qb_ipcs_connection_t * qb_ipcs_connection_next_get(qb_ipcs_service_t* pt,
qb_ipcs_connection_t *current);
/**
* Set the permissions on and shared memory files so that both processes can
* read and write to them.
*
* @param conn connection instance
* @param uid the user id to set.
* @param gid the group id to set.
* @param mode the mode to set.
*
* @see chmod() chown()
* @note this must be called within the qb_ipcs_connection_accept_fn()
* callback.
*/
void qb_ipcs_connection_auth_set(qb_ipcs_connection_t *conn, uid_t uid,
gid_t gid, mode_t mode);
/* *INDENT-OFF* */
#ifdef __cplusplus
}

View File

@ -98,6 +98,12 @@ extern "C" {
* LOG_INFO - LOG_DEBUG);
* @endcode
*
* To ensure all logs to file targets are fsync'ed (default QB_FALSE)
* @code
* qb_log_ctl(mytarget, QB_LOG_CONF_FILE_SYNC, QB_TRUE);
* @endcode
*
*
* @par Filtering messages.
* To have more power over what log messages go to which target you can apply
* filters to the targets. What happens is the desired callsites have the
@ -393,6 +399,7 @@ enum qb_log_conf {
QB_LOG_CONF_THREADED,
QB_LOG_CONF_PRIORITY_BUMP,
QB_LOG_CONF_STATE_GET,
QB_LOG_CONF_FILE_SYNC,
};
enum qb_log_filter_type {

View File

@ -239,7 +239,7 @@ int32_t qb_loop_poll_del(qb_loop_t *l, int32_t fd);
*
* @param l pointer to the loop instance
* @param p the priority
* @param signal (SIGHUP or SIGINT) etc ....
* @param sig (SIGHUP or SIGINT) etc ....
* @param data user data passed into the dispatch function
* @param dispatch_fn callback function
* @param handle (out) a reference to the signal job
@ -247,7 +247,7 @@ int32_t qb_loop_poll_del(qb_loop_t *l, int32_t fd);
*/
int32_t qb_loop_signal_add(qb_loop_t *l,
enum qb_loop_priority p,
int32_t signal,
int32_t sig,
void *data,
qb_loop_signal_dispatch_fn dispatch_fn,
qb_loop_signal_handle *handle);
@ -257,7 +257,7 @@ int32_t qb_loop_signal_add(qb_loop_t *l,
*
* @param l pointer to the loop instance
* @param p the priority
* @param signal (SIGHUP or SIGINT) etc ....
* @param sig (SIGHUP or SIGINT) etc ....
* @param data user data passed into the dispatch function
* @param dispatch_fn callback function
* @param handle (in) a reference to the signal job
@ -265,7 +265,7 @@ int32_t qb_loop_signal_add(qb_loop_t *l,
*/
int32_t qb_loop_signal_mod(qb_loop_t *l,
enum qb_loop_priority p,
int32_t signal,
int32_t sig,
void *data,
qb_loop_signal_dispatch_fn dispatch_fn,
qb_loop_signal_handle handle);

View File

@ -99,6 +99,13 @@ extern "C" {
*/
#define QB_RB_FLAG_SHARED_PROCESS 0x08
/**
* Don't use semaphores, only atomic ops.
* This mean that the timeout passed into qb_rb_chunk_read()
* will be ignored.
*/
#define QB_RB_FLAG_NO_SEMAPHORE 0x10
struct qb_ringbuffer_s;
typedef struct qb_ringbuffer_s qb_ringbuffer_t;
@ -278,6 +285,14 @@ qb_ringbuffer_t *qb_rb_create_from_file(int32_t fd, uint32_t flags);
*/
int32_t qb_rb_chown(qb_ringbuffer_t * rb, uid_t owner, gid_t group);
/**
* Like 'chmod' it changes the mode of the ringbuffers resources.
* @param mode mode to change to
* @param rb ringbuffer instance
* @retval 0 == ok
* @retval -errno for error
*/
int32_t qb_rb_chmod(qb_ringbuffer_t * rb, mode_t mode);
/* *INDENT-OFF* */
#ifdef __cplusplus

View File

@ -32,7 +32,7 @@ typedef void *timer_handle;
#define TIMER_HANDLE
#endif
static int64_t timerlist_hertz = HZ;
static int64_t timerlist_hertz;
struct timerlist {
struct qb_list_head timer_head;

View File

@ -21,26 +21,49 @@
MAINTAINERCLEANFILES = Makefile.in
noinst_HEADERS = ipc_int.h util_int.h ringbuffer_int.h loop_int.h log_int.h map_int.h
noinst_HEADERS = ipc_int.h util_int.h ringbuffer_int.h loop_int.h \
log_int.h map_int.h rpl_sem.h loop_poll_int.h
#
# Here are a set of rules to help you update your library version information:
# Start with version information of 0:0:0 for each libtool library.
# Update the version information only immediately before a public release of your software.
# More frequent updates are unnecessary, and only guarantee that the current interface number gets larger faster.
# If the library source code has changed at all since the last update, then increment revision (c:r:a becomes c:r+1:a).
# If any interfaces have been added, removed, or changed since the last update, increment current, and set revision to 0.
# If any interfaces have been added since the last public release, then increment age.
# If any interfaces have been removed since the last public release, then set age to 0.
#
AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
lib_LTLIBRARIES = libqb.la
libqb_la_LDFLAGS = -version-info 11:1:11
source_to_lint = util.c hdb.c ringbuffer.c ringbuffer_helper.c array.c \
loop.c loop_poll.c loop_job.c loop_timerlist.c \
ipcc.c ipcs.c ipc_shm.c ipc_us.c \
# From: http://sourceware.org/autobook/autobook/autobook_91.html
# (for my own sanity).
#
# 1) If you have changed any of the sources for this library, the revision
# number must be incremented. This is a new revision of the current
# interface.
#
# 2) If the interface has changed, then current must be incremented, and
# revision reset to `0'. This is the first revision of a new interface.
#
# 3) If the new interface is a superset of the previous interface
# (that is, if the previous interface has not been broken by the changes
# in this new release), then age must be incremented. This release is
# backwards compatible with the previous release.
#
# 4) If the new interface has removed elements with respect to the previous
# interface, then you have broken backward compatibility and age must be
# reset to `0'. This release has a new, but backwards incompatible
# interface. For example, if the next release of the library included
# some new commands for an existing socket protocol, you would use
# -version-info 1:0:1. This is the first revision of a new interface.
# This release is backwards compatible with the previous release.
# Later, you implement a faster way of handling part of the algorithm
# at the core of the library, and release it with -version-info 1:1:1.
# This is a new revision of the current interface.
# Unfortunately the speed of your new implementation can only be fully
# exploited by changing the API to access the structures at a lower level,
# which breaks compatibility with the previous interface, so you release
# it as -version-info 2:0:0. This release has a new, but backwards
# incompatible interface.
#
libqb_la_LDFLAGS = -version-info 14:2:14
source_to_lint = util.c hdb.c ringbuffer.c ringbuffer_helper.c \
array.c loop.c loop_poll.c loop_job.c \
loop_timerlist.c ipcc.c ipcs.c ipc_shm.c ipc_us.c \
log.c log_thread.c log_blackbox.c log_file.c \
log_syslog.c log_dcs.c log_format.c \
map.c skiplist.c hashtable.c trie.c
@ -48,13 +71,21 @@ source_to_lint = util.c hdb.c ringbuffer.c ringbuffer_helper.c array.c \
libqb_la_SOURCES = $(source_to_lint) unix.c
libqb_la_LIBADD = @LTLIBOBJS@
if HAVE_SYSV_MQ
libqb_la_SOURCES+=ipc_sysv_mq.c
if HAVE_SEM_TIMEDWAIT
else
libqb_la_SOURCES+=rpl_sem.c
endif
if HAVE_POSIX_MQ
libqb_la_SOURCES+=ipc_posix_mq.c
if HAVE_EPOLL
libqb_la_SOURCES+=loop_poll_epoll.c
else
if HAVE_KQUEUE
libqb_la_SOURCES+=loop_poll_kqueue.c
else
libqb_la_SOURCES+=loop_poll_poll.c
endif
endif
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libqb.pc
@ -62,8 +93,11 @@ pkgconfig_DATA = libqb.pc
if HAVE_SPLINT
check_SCRIPTS = run_splint.sh
TESTS = $(check_SCRIPTS)
# this is a hack because debian/ubuntu don't set the arch path
# in splint.
DEB_INCLUDES = -I/usr/include/x86_64-linux-gnu -I/usr/include/i386-linux-gnu
ALL_LINT_FLAGS = $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
ALL_LINT_FLAGS = $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(DEB_INCLUDES) \
$(libqb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CPPFLAGS) \
$(LINT_FLAGS)

View File

@ -56,8 +56,10 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
@HAVE_SYSV_MQ_TRUE@am__append_1 = ipc_sysv_mq.c
@HAVE_POSIX_MQ_TRUE@am__append_2 = ipc_posix_mq.c
@HAVE_SEM_TIMEDWAIT_FALSE@am__append_1 = rpl_sem.c
@HAVE_EPOLL_TRUE@am__append_2 = loop_poll_epoll.c
@HAVE_EPOLL_FALSE@@HAVE_KQUEUE_TRUE@am__append_3 = loop_poll_kqueue.c
@HAVE_EPOLL_FALSE@@HAVE_KQUEUE_FALSE@am__append_4 = loop_poll_poll.c
subdir = lib
DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in $(srcdir)/libqb.pc.in strchrnul.c \
@ -109,16 +111,21 @@ am__libqb_la_SOURCES_DIST = util.c hdb.c ringbuffer.c \
loop_timerlist.c ipcc.c ipcs.c ipc_shm.c ipc_us.c log.c \
log_thread.c log_blackbox.c log_file.c log_syslog.c log_dcs.c \
log_format.c map.c skiplist.c hashtable.c trie.c unix.c \
ipc_sysv_mq.c ipc_posix_mq.c
rpl_sem.c loop_poll_epoll.c loop_poll_kqueue.c \
loop_poll_poll.c
am__objects_1 = util.lo hdb.lo ringbuffer.lo ringbuffer_helper.lo \
array.lo loop.lo loop_poll.lo loop_job.lo loop_timerlist.lo \
ipcc.lo ipcs.lo ipc_shm.lo ipc_us.lo log.lo log_thread.lo \
log_blackbox.lo log_file.lo log_syslog.lo log_dcs.lo \
log_format.lo map.lo skiplist.lo hashtable.lo trie.lo
@HAVE_SYSV_MQ_TRUE@am__objects_2 = ipc_sysv_mq.lo
@HAVE_POSIX_MQ_TRUE@am__objects_3 = ipc_posix_mq.lo
@HAVE_SEM_TIMEDWAIT_FALSE@am__objects_2 = rpl_sem.lo
@HAVE_EPOLL_TRUE@am__objects_3 = loop_poll_epoll.lo
@HAVE_EPOLL_FALSE@@HAVE_KQUEUE_TRUE@am__objects_4 = \
@HAVE_EPOLL_FALSE@@HAVE_KQUEUE_TRUE@ loop_poll_kqueue.lo
@HAVE_EPOLL_FALSE@@HAVE_KQUEUE_FALSE@am__objects_5 = \
@HAVE_EPOLL_FALSE@@HAVE_KQUEUE_FALSE@ loop_poll_poll.lo
am_libqb_la_OBJECTS = $(am__objects_1) unix.lo $(am__objects_2) \
$(am__objects_3)
$(am__objects_3) $(am__objects_4) $(am__objects_5)
libqb_la_OBJECTS = $(am_libqb_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@ -127,7 +134,7 @@ libqb_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libqb_la_LDFLAGS) $(LDFLAGS) -o $@
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include -I$(top_builddir)/include/qb
depcomp = $(SHELL) $(top_srcdir)/depcomp
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
@ -158,106 +165,8 @@ DATA = $(pkgconfig_DATA)
HEADERS = $(noinst_HEADERS)
ETAGS = etags
CTAGS = ctags
# If stdout is a non-dumb tty, use colors. If test -t is not supported,
# then this fails; a conservative approach. Of course do not redirect
# stdout here, just stderr.
am__tty_colors = \
red=; grn=; lgn=; blu=; std=; \
test "X$(AM_COLOR_TESTS)" != Xno \
&& test "X$$TERM" != Xdumb \
&& { test "X$(AM_COLOR_TESTS)" = Xalways || test -t 1 2>/dev/null; } \
&& { \
red=''; \
grn=''; \
lgn=''; \
blu=''; \
std=''; \
}
# Restructured Text title and section.
am__rst_title = sed 's/.*/ & /;h;s/./=/g;p;x;p;g;p;s/.*//'
am__rst_section = sed 'p;s/./=/g;p;g'
# Put stdin (possibly several lines separated by ". ") in a box.
# Prefix each line by 'col' and terminate each with 'std', for coloring.
# Multi line coloring is problematic with "less -R", so we really need
# to color each line individually.
am__text_box = $(AWK) '{ \
n = split($$0, lines, "\\. "); max = 0; \
for (i = 1; i <= n; ++i) \
if (max < length(lines[i])) \
max = length(lines[i]); \
for (i = 0; i < max; ++i) \
line = line "="; \
print col line std; \
for (i = 1; i <= n; ++i) \
if (lines[i]) \
print col lines[i] std; \
print col line std; \
}'
# Solaris 10 'make', and several other traditional 'make' implementations,
# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
# by disabling -e (using the XSI extension "set +e") if it's set.
am__sh_e_setup = case $$- in *e*) set +e;; esac
# To be inserted before the command running the test. Creates the
# directory for the log if needed. Stores in $dir the directory
# containing $f, in $tst the test, in $log the log, and passes
# TESTS_ENVIRONMENT. Save and restore TERM around use of
# TESTS_ENVIRONMENT, in case that unsets it.
am__check_pre = \
$(am__sh_e_setup); \
$(am__vpath_adj_setup) $(am__vpath_adj) \
srcdir=$(srcdir); export srcdir; \
rm -f $@-t; \
am__trap='rm -f '\''$(abs_builddir)/$@-t'\''; (exit $$st); exit $$st'; \
trap "st=129; $$am__trap" 1; trap "st=130; $$am__trap" 2; \
trap "st=141; $$am__trap" 13; trap "st=143; $$am__trap" 15; \
am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`; \
test "x$$am__odir" = x. || $(MKDIR_P) "$$am__odir" || exit $$?; \
if test -f "./$$f"; then dir=./; \
elif test -f "$$f"; then dir=; \
else dir="$(srcdir)/"; fi; \
tst=$$dir$$f; log='$@'; __SAVED_TERM=$$TERM; \
$(TESTS_ENVIRONMENT)
# To be appended to the command running the test. Handle the stdout
# and stderr redirection, and catch the exit status.
am__check_post = \
>$@-t 2>&1; \
estatus=$$?; \
if test -n '$(DISABLE_HARD_ERRORS)' \
&& test $$estatus -eq 99; then \
estatus=1; \
fi; \
TERM=$$__SAVED_TERM; export TERM; \
$(am__tty_colors); \
xfailed=PASS; \
case " $(XFAIL_TESTS) " in \
*[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
xfailed=XFAIL;; \
esac; \
case $$estatus.$$xfailed in \
0.XFAIL) col=$$red; res=XPASS;; \
0.*) col=$$grn; res=PASS ;; \
77.*) col=$$blu; res=SKIP ;; \
99.*) col=$$red; res=FAIL ;; \
*.XFAIL) col=$$lgn; res=XFAIL;; \
*.*) col=$$red; res=FAIL ;; \
esac; \
echo "$${col}$$res$${std}: $$f"; \
echo "$$res: $$f (exit: $$estatus)" | \
$(am__rst_section) >$@; \
cat $@-t >>$@; \
rm -f $@-t
RECHECK_LOGS = $(TEST_LOGS)
AM_RECURSIVE_TARGETS = check recheck check-html recheck-html
TEST_SUITE_HTML = $(TEST_SUITE_LOG:.log=.html)
TEST_SUITE_LOG = test-suite.log
TEST_EXTENSIONS = @EXEEXT@ .test
LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
am__test_logs1 = $(TESTS:=.log)
am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
TEST_LOGS = $(am__test_logs2:.test.log=.log)
TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
$(TEST_LOG_FLAGS)
TEST_LOGS_TMP = $(TEST_LOGS:.log=.log-t)
red=; grn=; lgn=; blu=; std=
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
@ -305,7 +214,6 @@ LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIB_RT = @LIB_RT@
LINT_FLAGS = @LINT_FLAGS@
LIPO = @LIPO@
LN_S = @LN_S@
@ -393,43 +301,69 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
MAINTAINERCLEANFILES = Makefile.in
noinst_HEADERS = ipc_int.h util_int.h ringbuffer_int.h loop_int.h log_int.h map_int.h
noinst_HEADERS = ipc_int.h util_int.h ringbuffer_int.h loop_int.h \
log_int.h map_int.h rpl_sem.h loop_poll_int.h
#
# Here are a set of rules to help you update your library version information:
# Start with version information of 0:0:0 for each libtool library.
# Update the version information only immediately before a public release of your software.
# More frequent updates are unnecessary, and only guarantee that the current interface number gets larger faster.
# If the library source code has changed at all since the last update, then increment revision (c:r:a becomes c:r+1:a).
# If any interfaces have been added, removed, or changed since the last update, increment current, and set revision to 0.
# If any interfaces have been added since the last public release, then increment age.
# If any interfaces have been removed since the last public release, then set age to 0.
#
AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
lib_LTLIBRARIES = libqb.la
libqb_la_LDFLAGS = -version-info 11:1:11
source_to_lint = util.c hdb.c ringbuffer.c ringbuffer_helper.c array.c \
loop.c loop_poll.c loop_job.c loop_timerlist.c \
ipcc.c ipcs.c ipc_shm.c ipc_us.c \
# From: http://sourceware.org/autobook/autobook/autobook_91.html
# (for my own sanity).
#
# 1) If you have changed any of the sources for this library, the revision
# number must be incremented. This is a new revision of the current
# interface.
#
# 2) If the interface has changed, then current must be incremented, and
# revision reset to `0'. This is the first revision of a new interface.
#
# 3) If the new interface is a superset of the previous interface
# (that is, if the previous interface has not been broken by the changes
# in this new release), then age must be incremented. This release is
# backwards compatible with the previous release.
#
# 4) If the new interface has removed elements with respect to the previous
# interface, then you have broken backward compatibility and age must be
# reset to `0'. This release has a new, but backwards incompatible
# interface. For example, if the next release of the library included
# some new commands for an existing socket protocol, you would use
# -version-info 1:0:1. This is the first revision of a new interface.
# This release is backwards compatible with the previous release.
# Later, you implement a faster way of handling part of the algorithm
# at the core of the library, and release it with -version-info 1:1:1.
# This is a new revision of the current interface.
# Unfortunately the speed of your new implementation can only be fully
# exploited by changing the API to access the structures at a lower level,
# which breaks compatibility with the previous interface, so you release
# it as -version-info 2:0:0. This release has a new, but backwards
# incompatible interface.
#
libqb_la_LDFLAGS = -version-info 14:2:14
source_to_lint = util.c hdb.c ringbuffer.c ringbuffer_helper.c \
array.c loop.c loop_poll.c loop_job.c \
loop_timerlist.c ipcc.c ipcs.c ipc_shm.c ipc_us.c \
log.c log_thread.c log_blackbox.c log_file.c \
log_syslog.c log_dcs.c log_format.c \
map.c skiplist.c hashtable.c trie.c
libqb_la_SOURCES = $(source_to_lint) unix.c $(am__append_1) \
$(am__append_2)
$(am__append_2) $(am__append_3) $(am__append_4)
libqb_la_LIBADD = @LTLIBOBJS@
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libqb.pc
@HAVE_SPLINT_TRUE@check_SCRIPTS = run_splint.sh
@HAVE_SPLINT_TRUE@TESTS = $(check_SCRIPTS)
@HAVE_SPLINT_TRUE@ALL_LINT_FLAGS = $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
# this is a hack because debian/ubuntu don't set the arch path
# in splint.
@HAVE_SPLINT_TRUE@DEB_INCLUDES = -I/usr/include/x86_64-linux-gnu -I/usr/include/i386-linux-gnu
@HAVE_SPLINT_TRUE@ALL_LINT_FLAGS = $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(DEB_INCLUDES) \
@HAVE_SPLINT_TRUE@ $(libqb_la_CPPFLAGS) $(CPPFLAGS) $(AM_CPPFLAGS) \
@HAVE_SPLINT_TRUE@ $(LINT_FLAGS)
all: all-am
.SUFFIXES:
.SUFFIXES: .c .html .lo .log .o .obj .test .test$(EXEEXT)
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
@ -508,9 +442,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/array.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hashtable.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hdb.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipc_posix_mq.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipc_shm.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipc_sysv_mq.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipc_us.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipcc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipcs.Plo@am__quote@
@ -524,10 +456,14 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loop.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loop_job.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loop_poll.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loop_poll_epoll.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loop_poll_kqueue.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loop_poll_poll.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loop_timerlist.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ringbuffer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ringbuffer_helper.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpl_sem.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/skiplist.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trie.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unix.Plo@am__quote@
@ -630,139 +566,98 @@ GTAGS:
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
$(TEST_SUITE_LOG): $(TEST_LOGS)
@$(am__sh_e_setup); \
list='$(TEST_LOGS)'; \
results=`for f in $$list; do \
test -r $$f && read line < $$f && echo "$$line" \
|| echo FAIL; \
done`; \
all=`echo "$$results" | sed '/^$$/d' | wc -l | sed -e 's/^[ ]*//'`; \
fail=`echo "$$results" | grep -c '^FAIL'`; \
pass=`echo "$$results" | grep -c '^PASS'`; \
skip=`echo "$$results" | grep -c '^SKIP'`; \
xfail=`echo "$$results" | grep -c '^XFAIL'`; \
xpass=`echo "$$results" | grep -c '^XPASS'`; \
failures=`expr $$fail + $$xpass`; \
all=`expr $$all - $$skip`; \
if test "$$all" -eq 1; then tests=test; All=; \
else tests=tests; All="All "; fi; \
case fail=$$fail:xpass=$$xpass:xfail=$$xfail in \
fail=0:xpass=0:xfail=0) \
msg="$$All$$all $$tests passed. "; \
exit=true;; \
fail=0:xpass=0:xfail=*) \
msg="$$All$$all $$tests behaved as expected"; \
if test "$$xfail" -eq 1; then xfailures=failure; \
else xfailures=failures; fi; \
msg="$$msg ($$xfail expected $$xfailures). "; \
exit=true;; \
fail=*:xpass=0:xfail=*) \
msg="$$fail of $$all $$tests failed. "; \
exit=false;; \
fail=*:xpass=*:xfail=*) \
msg="$$failures of $$all $$tests did not behave as expected"; \
if test "$$xpass" -eq 1; then xpasses=pass; \
else xpasses=passes; fi; \
msg="$$msg ($$xpass unexpected $$xpasses). "; \
exit=false;; \
*) \
echo >&2 "incorrect case"; exit 4;; \
esac; \
if test "$$skip" -ne 0; then \
if test "$$skip" -eq 1; then \
msg="$$msg($$skip test was not run). "; \
else \
msg="$$msg($$skip tests were not run). "; \
fi; \
fi; \
{ \
echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
$(am__rst_title); \
echo "$$msg"; \
echo; \
echo ".. contents:: :depth: 2"; \
echo; \
for f in $$list; do \
test -r $$f && read line < $$f || line=; \
case $$line in \
PASS:*|XFAIL:*);; \
*) echo; cat $$f;; \
esac; \
done; \
} >$(TEST_SUITE_LOG).tmp; \
mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
if test "$$failures" -ne 0; then \
msg="$${msg}See $(subdir)/$(TEST_SUITE_LOG). "; \
if test -n "$(PACKAGE_BUGREPORT)"; then \
msg="$${msg}Please report to $(PACKAGE_BUGREPORT). "; \
fi; \
fi; \
test x"$$VERBOSE" = x || $$exit || cat $(TEST_SUITE_LOG); \
$(am__tty_colors); \
if $$exit; then \
col="$$grn"; \
else \
col="$$red"; \
fi; \
echo "$$msg" | $(am__text_box) "col=$$col" "std=$$std"; \
$$exit || exit 1
check-TESTS recheck:
@if test $@ != recheck; then \
list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list; \
fi
@test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
@list='' list2='$(TEST_LOGS)'; for f in $$list2; do \
test .log = $$f && continue; \
if test $@ = recheck; then \
test -f $$f || continue; \
if test -r $$f && read line < $$f; then \
case $$line in FAIL*|XPASS*) : ;; *) continue;; esac; \
check-TESTS: $(TESTS)
@failed=0; all=0; xfail=0; xpass=0; skip=0; \
srcdir=$(srcdir); export srcdir; \
list=' $(TESTS) '; \
$(am__tty_colors); \
if test -n "$$list"; then \
for tst in $$list; do \
if test -f ./$$tst; then dir=./; \
elif test -f $$tst; then dir=; \
else dir="$(srcdir)/"; fi; \
if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
all=`expr $$all + 1`; \
case " $(XFAIL_TESTS) " in \
*[\ \ ]$$tst[\ \ ]*) \
xpass=`expr $$xpass + 1`; \
failed=`expr $$failed + 1`; \
col=$$red; res=XPASS; \
;; \
*) \
col=$$grn; res=PASS; \
;; \
esac; \
elif test $$? -ne 77; then \
all=`expr $$all + 1`; \
case " $(XFAIL_TESTS) " in \
*[\ \ ]$$tst[\ \ ]*) \
xfail=`expr $$xfail + 1`; \
col=$$lgn; res=XFAIL; \
;; \
*) \
failed=`expr $$failed + 1`; \
col=$$red; res=FAIL; \
;; \
esac; \
else \
skip=`expr $$skip + 1`; \
col=$$blu; res=SKIP; \
fi; \
echo "$${col}$$res$${std}: $$tst"; \
done; \
if test "$$all" -eq 1; then \
tests="test"; \
All=""; \
else \
tests="tests"; \
All="All "; \
fi; \
if test "$$failed" -eq 0; then \
if test "$$xfail" -eq 0; then \
banner="$$All$$all $$tests passed"; \
else \
if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
fi; \
else \
if test "$$xpass" -eq 0; then \
banner="$$failed of $$all $$tests failed"; \
else \
if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
fi; \
fi; \
if test -z "$$list"; then list=$$f; else list="$$list $$f"; fi; \
done; \
if test $@ = recheck && test -n "$$list"; then \
echo "am--clean: ; rm -f $$list" \
| $(MAKE) $(AM_MAKEFLAGS) -f - am--clean || exit 1; \
fi; \
$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$list"
recheck: $(check_SCRIPTS)
am--mostlyclean-test-html:
list='$(TEST_LOGS:.log=.html)'; test -z "$$list" || rm -f $$list
rm -f $(TEST_SUITE_HTML)
.log.html:
@list='$(RST2HTML) $$RST2HTML rst2html rst2html.py'; \
for r2h in $$list; do \
if ($$r2h --version) >/dev/null 2>&1; then \
R2H=$$r2h; \
fi; \
done; \
if test -z "$$R2H"; then \
echo >&2 "cannot find rst2html, cannot create $@"; \
exit 2; \
fi; \
$$R2H $< >$@.tmp
@mv $@.tmp $@
# Be sure to run check first, and then to convert the result.
# Beware of concurrent executions. Run "check" not "check-TESTS", as
# check-SCRIPTS and other dependencies are rebuilt by the former only.
# And expect check to fail.
check-html recheck-html:
@target=`echo $@ | sed 's/-html$$//'`; \
rv=0; $(MAKE) $(AM_MAKEFLAGS) $$target || rv=$$?; \
$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_HTML) TEST_LOGS= || exit 4; \
exit $$rv
run_splint.sh.log: run_splint.sh
@p='run_splint.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
.test.log:
@p='$<'; $(am__check_pre) $(TEST_LOG_COMPILE) "$$tst" $(am__check_post)
@am__EXEEXT_TRUE@.test$(EXEEXT).log:
@am__EXEEXT_TRUE@ @p='$<'; $(am__check_pre) $(TEST_LOG_COMPILE) "$$tst" $(am__check_post)
dashes="$$banner"; \
skipped=""; \
if test "$$skip" -ne 0; then \
if test "$$skip" -eq 1; then \
skipped="($$skip test was not run)"; \
else \
skipped="($$skip tests were not run)"; \
fi; \
test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
dashes="$$skipped"; \
fi; \
report=""; \
if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
report="Please report to $(PACKAGE_BUGREPORT)"; \
test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
dashes="$$report"; \
fi; \
dashes=`echo "$$dashes" | sed s/./=/g`; \
if test "$$failed" -eq 0; then \
col="$$grn"; \
else \
col="$$red"; \
fi; \
echo "$${col}$$dashes$${std}"; \
echo "$${col}$$banner$${std}"; \
test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
test -z "$$report" || echo "$${col}$$report$${std}"; \
echo "$${col}$$dashes$${std}"; \
test "$$failed" -eq 0; \
else :; fi
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
@ -823,9 +718,6 @@ install-strip:
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
-test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
-test -z "$(TEST_LOGS_TMP)" || rm -f $(TEST_LOGS_TMP)
-test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
@HAVE_SPLINT_FALSE@clean-generic:
@ -895,8 +787,8 @@ maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: am--mostlyclean-test-html mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
@ -908,22 +800,21 @@ ps-am:
uninstall-am: uninstall-libLTLIBRARIES uninstall-pkgconfigDATA
.MAKE: check-am check-html install-am install-strip recheck-html
.MAKE: check-am install-am install-strip
.PHONY: CTAGS GTAGS all all-am am--mostlyclean-test-html check \
check-TESTS check-am check-html clean clean-generic \
clean-libLTLIBRARIES clean-libtool ctags distclean \
distclean-compile distclean-generic distclean-libtool \
distclean-tags distdir dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am \
install-libLTLIBRARIES install-man install-pdf install-pdf-am \
install-pkgconfigDATA install-ps install-ps-am install-strip \
installcheck installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
recheck recheck-html tags uninstall uninstall-am \
.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
clean-generic clean-libLTLIBRARIES clean-libtool ctags \
distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-libLTLIBRARIES install-man install-pdf \
install-pdf-am install-pkgconfigDATA install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
pdf pdf-am ps ps-am tags uninstall uninstall-am \
uninstall-libLTLIBRARIES uninstall-pkgconfigDATA

View File

@ -103,7 +103,7 @@ qb_array_index(struct qb_array * a, int32_t idx, void **element_out)
int32_t b;
int32_t elem;
char *bin;
int32_t rc;
int32_t rc = 0;
if (a == NULL || element_out == NULL) {
return -EINVAL;
@ -207,6 +207,7 @@ qb_array_free(struct qb_array *a)
for (i = 0; i < a->num_bins; i++) {
free(a->bin[i]);
}
free(a->bin);
(void)qb_thread_lock_destroy(a->grow_lock);
free(a);
}

View File

@ -25,9 +25,6 @@
#include "os_base.h"
#include <dirent.h>
#ifdef HAVE_MQUEUE_H
#include <mqueue.h>
#endif /* HAVE_MQUEUE_H */
#include <qb/qblist.h>
#include <qb/qbloop.h>
#include <qb/qbipcc.h>
@ -35,10 +32,6 @@
#include <qb/qbipc_common.h>
#include <qb/qbrb.h>
#ifdef HAVE_POSIX_SHARED_SEMAPHORE
#include <semaphore.h>
#endif /* HAVE_POSIX_SHARED_SEMAPHORE */
#define QB_IPC_MAX_WAIT_MS 2000
/*
@ -50,23 +43,23 @@ SEND CONN REQ ->
*/
struct qb_ipc_connection_request {
struct qb_ipc_request_header hdr __attribute__ ((aligned(8)));
uint32_t max_msg_size __attribute__ ((aligned(8)));
struct qb_ipc_request_header hdr;
uint32_t max_msg_size;
} __attribute__ ((aligned(8)));
struct qb_ipc_event_connection_request {
struct qb_ipc_request_header hdr __attribute__ ((aligned(8)));
intptr_t connection __attribute__ ((aligned(8)));
struct qb_ipc_request_header hdr;
intptr_t connection;
} __attribute__ ((aligned(8)));
struct qb_ipc_connection_response {
struct qb_ipc_response_header hdr __attribute__ ((aligned(8)));
int32_t connection_type __attribute__ ((aligned(8)));
uint32_t max_msg_size __attribute__ ((aligned(8)));
intptr_t connection __attribute__ ((aligned(8)));
char request[PATH_MAX] __attribute__ ((aligned(8)));
char response[PATH_MAX] __attribute__ ((aligned(8)));
char event[PATH_MAX] __attribute__ ((aligned(8)));
struct qb_ipc_response_header hdr;
int32_t connection_type;
uint32_t max_msg_size;
intptr_t connection;
char request[PATH_MAX];
char response[PATH_MAX];
char event[PATH_MAX];
} __attribute__ ((aligned(8)));
struct qb_ipcc_connection;
@ -80,16 +73,6 @@ struct qb_ipc_one_way {
void* shared_data;
char shared_file_name[NAME_MAX];
} us;
#ifdef HAVE_MQUEUE_H
struct {
mqd_t q;
char name[NAME_MAX];
} pmq;
#endif
struct {
int32_t q;
int32_t key;
} smq;
struct {
qb_ringbuffer_t *rb;
} shm;
@ -122,13 +105,11 @@ int32_t qb_ipcc_us_setup_connect(struct qb_ipcc_connection *c,
struct qb_ipc_connection_response *r);
ssize_t qb_ipc_us_send(struct qb_ipc_one_way *one_way, const void *msg, size_t len);
ssize_t qb_ipc_us_recv(struct qb_ipc_one_way *one_way, void *msg, size_t len, int32_t timeout);
int32_t qb_ipc_us_recv_ready(struct qb_ipc_one_way *one_way, int32_t ms_timeout);
int32_t qb_ipc_us_ready(struct qb_ipc_one_way *one_way, int32_t ms_timeout, int32_t events);
void qb_ipcc_us_sock_close(int32_t sock);
int32_t qb_ipcc_pmq_connect(struct qb_ipcc_connection *c, struct qb_ipc_connection_response * response);
int32_t qb_ipcc_us_connect(struct qb_ipcc_connection *c, struct qb_ipc_connection_response * response);
int32_t qb_ipcc_smq_connect(struct qb_ipcc_connection *c, struct qb_ipc_connection_response * response);
int32_t qb_ipcc_shm_connect(struct qb_ipcc_connection *c, struct qb_ipc_connection_response * response);
struct qb_ipcs_service;
@ -173,12 +154,21 @@ enum qb_ipcs_connection_state {
QB_IPCS_CONNECTION_SHUTTING_DOWN,
};
#define CONNECTION_DESCRIPTION (16)
struct qb_ipcs_connection_auth {
uid_t uid;
gid_t gid;
mode_t mode;
};
struct qb_ipcs_connection {
enum qb_ipcs_connection_state state;
int32_t refcount;
pid_t pid;
uid_t euid;
gid_t egid;
struct qb_ipcs_connection_auth auth;
struct qb_ipc_one_way setup;
struct qb_ipc_one_way request;
struct qb_ipc_one_way response;
@ -190,12 +180,11 @@ struct qb_ipcs_connection {
int32_t fc_enabled;
int32_t poll_events;
int32_t outstanding_notifiers;
struct qb_ipcs_connection_stats stats;
char description[CONNECTION_DESCRIPTION];
struct qb_ipcs_connection_stats_2 stats;
};
void qb_ipcs_pmq_init(struct qb_ipcs_service *s);
void qb_ipcs_us_init(struct qb_ipcs_service *s);
void qb_ipcs_smq_init(struct qb_ipcs_service *s);
void qb_ipcs_shm_init(struct qb_ipcs_service *s);
int32_t qb_ipcs_us_publish(struct qb_ipcs_service *s);
@ -204,8 +193,11 @@ int32_t qb_ipcs_us_withdraw(struct qb_ipcs_service *s);
int32_t qb_ipcs_dispatch_connection_request(int32_t fd, int32_t revents, void *data);
int32_t qb_ipcs_dispatch_service_request(int32_t fd, int32_t revents, void *data);
struct qb_ipcs_connection* qb_ipcs_connection_alloc(struct qb_ipcs_service *s);
void qb_ipcs_sockets_disconnect(struct qb_ipcs_connection *c);
int32_t qb_ipcs_process_request(struct qb_ipcs_service *s,
struct qb_ipc_request_header *hdr);
int32_t qb_ipc_us_sock_error_is_disconnected(int err);
#endif /* QB_IPC_INT_H_DEFINED */

View File

@ -1,421 +0,0 @@
/*
* Copyright (C) 2010 Red Hat, Inc.
*
* Author: Angus Salkeld <asalkeld@redhat.com>
*
* This file is part of libqb.
*
* libqb 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.
*
* libqb 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 libqb. If not, see <http://www.gnu.org/licenses/>.
*/
#include "os_base.h"
#include <mqueue.h>
#include <sys/resource.h>
#include "ipc_int.h"
#include "util_int.h"
#include <qb/qbdefs.h>
#include <qb/qbutil.h>
#include <qb/qbloop.h>
#define QB_REQUEST_Q_LEN 3
#define QB_RESPONSE_Q_LEN 1
#define QB_EVENT_Q_LEN 3
static size_t q_space_used = 0;
#ifdef QB_LINUX
#define QB_RLIMIT_CHANGE_NEEDED 1
#endif /* QB_LINUX */
/*
* utility functions
* --------------------------------------------------------
*/
static int32_t
posix_mq_increase_limits(size_t max_msg_size, int32_t q_len)
{
int32_t res = 0;
#ifdef QB_RLIMIT_CHANGE_NEEDED
struct rlimit rlim;
size_t q_space_needed;
#endif /* QB_RLIMIT_CHANGE_NEEDED */
#ifdef QB_RLIMIT_CHANGE_NEEDED
if (getrlimit(RLIMIT_MSGQUEUE, &rlim) != 0) {
res = -errno;
qb_util_log(LOG_ERR, "getrlimit failed");
return res;
}
q_space_needed = q_space_used + (max_msg_size * q_len * 4 / 3);
qb_util_log(LOG_DEBUG, "rlimit:%d needed:%zu used:%zu",
(int)rlim.rlim_cur, q_space_needed, q_space_used);
if (rlim.rlim_cur < q_space_needed) {
rlim.rlim_cur = q_space_needed;
}
if (rlim.rlim_max < q_space_needed) {
rlim.rlim_max = q_space_needed;
}
if (setrlimit(RLIMIT_MSGQUEUE, &rlim) != 0) {
res = -errno;
qb_util_log(LOG_ERR, "setrlimit failed");
}
#endif /* QB_RLIMIT_CHANGE_NEEDED */
return res;
}
static int32_t
posix_mq_open(struct qb_ipc_one_way *one_way, const char *name, size_t q_len)
{
int32_t res = posix_mq_increase_limits(one_way->max_msg_size, q_len);
if (res != 0) {
return res;
}
one_way->u.pmq.q = mq_open(name, O_RDWR);
if (one_way->u.pmq.q == (mqd_t) - 1) {
res = -errno;
perror("mq_open");
return res;
}
(void)strlcpy(one_way->u.pmq.name, name, NAME_MAX);
q_space_used += one_way->max_msg_size * q_len;
return 0;
}
static int32_t
posix_mq_create(struct qb_ipcs_connection *c,
struct qb_ipc_one_way *one_way, const char *name, size_t q_len)
{
struct mq_attr attr;
mqd_t q = 0;
int32_t res = 0;
mode_t m = 0600;
size_t max_msg_size = one_way->max_msg_size;
res = posix_mq_increase_limits(max_msg_size, q_len);
if (res != 0) {
return res;
}
try_smaller:
if (q != 0) {
max_msg_size = max_msg_size / 2;
q_len--;
}
attr.mq_flags = O_NONBLOCK;
attr.mq_maxmsg = q_len;
attr.mq_msgsize = max_msg_size;
q = mq_open(name, O_RDWR | O_CREAT | O_EXCL | O_NONBLOCK, m, &attr);
if (q == (mqd_t) - 1 && errno == ENOMEM) {
if (max_msg_size > 9000 && q_len > 3) {
goto try_smaller;
}
}
if (q == (mqd_t) - 1) {
res = -errno;
qb_util_perror(LOG_ERR, "Can't create mq \"%s\"", name);
return res;
}
q_space_used += max_msg_size * q_len;
one_way->max_msg_size = max_msg_size;
one_way->u.pmq.q = q;
(void)strlcpy(one_way->u.pmq.name, name, NAME_MAX);
res = fchown((int)q, c->euid, c->egid);
if (res == -1) {
res = -errno;
qb_util_perror(LOG_ERR, "fchown:%s", name);
mq_close(q);
mq_unlink(name);
}
return res;
}
static ssize_t
qb_ipc_pmq_send(struct qb_ipc_one_way *one_way,
const void *msg_ptr, size_t msg_len)
{
int32_t res = mq_send(one_way->u.pmq.q, msg_ptr, msg_len, 1);
if (res != 0) {
return -errno;
}
return msg_len;
}
static ssize_t
qb_ipc_pmq_sendv(struct qb_ipc_one_way *one_way,
const struct iovec *iov, size_t iov_len)
{
int32_t total_size = 0;
int32_t i;
int32_t res = 0;
char *data = NULL;
char *pt = NULL;
for (i = 0; i < iov_len; i++) {
total_size += iov[i].iov_len;
}
if (total_size == 0) {
return -EINVAL;
}
data = malloc(total_size);
if (data == NULL) {
return -ENOMEM;
}
pt = data;
for (i = 0; i < iov_len; i++) {
memcpy(pt, iov[i].iov_base, iov[i].iov_len);
pt += iov[i].iov_len;
}
res = mq_send(one_way->u.pmq.q, data, total_size, 1);
free(data);
if (res != 0) {
return -errno;
}
return total_size;
}
static ssize_t
qb_ipc_pmq_recv(struct qb_ipc_one_way *one_way,
void *msg_ptr, size_t msg_len, int32_t ms_timeout)
{
uint32_t msg_prio;
struct timespec ts_timeout;
ssize_t res;
if (ms_timeout >= 0) {
qb_util_timespec_from_epoch_get(&ts_timeout);
qb_timespec_add_ms(&ts_timeout, ms_timeout);
}
mq_receive_again:
if (ms_timeout >= 0) {
res = mq_timedreceive(one_way->u.pmq.q,
(char *)msg_ptr,
one_way->max_msg_size,
&msg_prio, &ts_timeout);
} else {
res = mq_receive(one_way->u.pmq.q,
(char *)msg_ptr,
one_way->max_msg_size, &msg_prio);
}
if (res == -1) {
switch (errno) {
case EINTR:
goto mq_receive_again;
break;
case EAGAIN:
res = -ETIMEDOUT;
break;
case ETIMEDOUT:
res = -errno;
break;
default:
res = -errno;
qb_util_perror(LOG_ERR,
"error waiting for mq_timedreceive");
break;
}
}
return res;
}
/*
* client functions
* --------------------------------------------------------
*/
static void
qb_ipcc_pmq_disconnect(struct qb_ipcc_connection *c)
{
struct qb_ipc_request_header hdr;
qb_util_log(LOG_DEBUG, "%s()", __func__);
if (c->needs_sock_for_poll) {
return;
}
hdr.id = QB_IPC_MSG_DISCONNECT;
hdr.size = sizeof(hdr);
mq_send(c->request.u.pmq.q, (const char *)&hdr, hdr.size, 30);
mq_close(c->event.u.pmq.q);
mq_close(c->response.u.pmq.q);
mq_close(c->request.u.pmq.q);
mq_unlink(c->event.u.pmq.name);
mq_unlink(c->request.u.pmq.name);
mq_unlink(c->response.u.pmq.name);
}
int32_t
qb_ipcc_pmq_connect(struct qb_ipcc_connection *c,
struct qb_ipc_connection_response *response)
{
int32_t res = 0;
c->funcs.send = qb_ipc_pmq_send;
c->funcs.sendv = qb_ipc_pmq_sendv;
c->funcs.recv = qb_ipc_pmq_recv;
c->funcs.fc_get = NULL;
c->funcs.disconnect = qb_ipcc_pmq_disconnect;
#if defined(QB_LINUX) || defined(QB_BSD)
c->needs_sock_for_poll = QB_FALSE;
#else
c->needs_sock_for_poll = QB_TRUE;
#endif
if (strlen(c->name) > (NAME_MAX - 20)) {
return -EINVAL;
}
res = posix_mq_open(&c->request, response->request, QB_REQUEST_Q_LEN);
if (res != 0) {
perror("mq_open:REQUEST");
return res;
}
res = posix_mq_open(&c->response, response->response,
QB_RESPONSE_Q_LEN);
if (res != 0) {
perror("mq_open:RESPONSE");
goto cleanup_request;
}
res = posix_mq_open(&c->event, response->event, QB_EVENT_Q_LEN);
if (res != 0) {
perror("mq_open:EVENT");
goto cleanup_request_response;
}
return 0;
cleanup_request_response:
mq_close(c->response.u.pmq.q);
cleanup_request:
mq_close(c->request.u.pmq.q);
return res;
}
/*
* service functions
* --------------------------------------------------------
*/
static void
qb_ipcs_pmq_disconnect(struct qb_ipcs_connection *c)
{
struct qb_ipc_response_header msg;
msg.id = QB_IPC_MSG_DISCONNECT;
msg.size = sizeof(msg);
msg.error = 0;
(void)qb_ipc_pmq_send(&c->event, &msg, msg.size);
mq_close(c->event.u.pmq.q);
mq_close(c->response.u.pmq.q);
mq_close(c->request.u.pmq.q);
mq_unlink(c->event.u.pmq.name);
mq_unlink(c->request.u.pmq.name);
mq_unlink(c->response.u.pmq.name);
}
static int32_t
qb_ipcs_pmq_connect(struct qb_ipcs_service *s,
struct qb_ipcs_connection *c,
struct qb_ipc_connection_response *r)
{
int32_t res = 0;
snprintf(r->request, NAME_MAX, "/%s-request-%d", s->name, c->pid);
snprintf(r->response, NAME_MAX, "/%s-response-%d", s->name, c->pid);
snprintf(r->event, NAME_MAX, "/%s-event-%d", s->name, c->pid);
res = posix_mq_create(c, &c->request, r->request, QB_REQUEST_Q_LEN);
if (res < 0) {
goto cleanup;
}
res = posix_mq_create(c, &c->response, r->response, QB_RESPONSE_Q_LEN);
if (res < 0) {
goto cleanup_request;
}
res = posix_mq_create(c, &c->event, r->event, QB_EVENT_Q_LEN);
if (res < 0) {
goto cleanup_request_response;
}
if (!s->needs_sock_for_poll) {
res =
s->poll_fns.dispatch_add(s->poll_priority,
(int32_t) c->request.u.pmq.q,
POLLIN | POLLPRI | POLLNVAL, c,
qb_ipcs_dispatch_service_request);
}
r->hdr.error = 0;
return res;
cleanup_request_response:
mq_close(c->response.u.pmq.q);
mq_unlink(r->response);
cleanup_request:
mq_close(c->request.u.pmq.q);
mq_unlink(r->request);
cleanup:
r->hdr.error = res;
return res;
}
static ssize_t
qb_ipc_pmq_q_len_get(struct qb_ipc_one_way *one_way)
{
struct mq_attr info;
int32_t res = mq_getattr(one_way->u.pmq.q, &info);
if (res == 0) {
return info.mq_curmsgs;
}
return -errno;
}
void
qb_ipcs_pmq_init(struct qb_ipcs_service *s)
{
s->funcs.connect = qb_ipcs_pmq_connect;
s->funcs.disconnect = qb_ipcs_pmq_disconnect;
s->funcs.recv = qb_ipc_pmq_recv;
s->funcs.send = qb_ipc_pmq_send;
s->funcs.sendv = qb_ipc_pmq_sendv;
s->funcs.peek = NULL;
s->funcs.reclaim = NULL;
s->funcs.fc_set = NULL;
s->funcs.q_len_get = qb_ipc_pmq_q_len_get;
#if defined(QB_LINUX) || defined(QB_BSD)
s->needs_sock_for_poll = QB_FALSE;
#else
s->needs_sock_for_poll = QB_TRUE;
#endif
}

View File

@ -106,10 +106,15 @@ static ssize_t
qb_ipc_shm_peek(struct qb_ipc_one_way *one_way, void **data_out,
int32_t ms_timeout)
{
ssize_t rc;
if (one_way->u.shm.rb == NULL) {
return -ENOTCONN;
}
return qb_rb_chunk_peek(one_way->u.shm.rb, data_out, ms_timeout);
rc = qb_rb_chunk_peek(one_way->u.shm.rb, data_out, ms_timeout);
if (rc == 0) {
return -EAGAIN;
}
return rc;
}
static void
@ -233,6 +238,40 @@ qb_ipcs_shm_disconnect(struct qb_ipcs_connection *c)
}
}
static int32_t
qb_ipcs_shm_rb_open(struct qb_ipcs_connection *c,
struct qb_ipc_one_way *ow,
const char *rb_name)
{
int32_t res = 0;
ow->u.shm.rb = qb_rb_open(rb_name,
ow->max_msg_size,
QB_RB_FLAG_CREATE |
QB_RB_FLAG_SHARED_PROCESS,
sizeof(int32_t));
if (ow->u.shm.rb == NULL) {
res = -errno;
qb_util_perror(LOG_ERR, "qb_rb_open:%s", rb_name);
return res;
}
res = qb_rb_chown(ow->u.shm.rb, c->auth.uid, c->auth.gid);
if (res != 0) {
qb_util_perror(LOG_ERR, "qb_rb_chown:%s", rb_name);
goto cleanup;
}
res = qb_rb_chmod(ow->u.shm.rb, c->auth.mode);
if (res != 0) {
qb_util_perror(LOG_ERR, "qb_rb_chmod:%s", rb_name);
goto cleanup;
}
return res;
cleanup:
qb_rb_close(ow->u.shm.rb);
return res;
}
static int32_t
qb_ipcs_shm_connect(struct qb_ipcs_service *s,
struct qb_ipcs_connection *c,
@ -242,66 +281,34 @@ qb_ipcs_shm_connect(struct qb_ipcs_service *s,
qb_util_log(LOG_DEBUG, "connecting to client [%d]", c->pid);
snprintf(r->request, NAME_MAX, "%s-request-%d-%d", s->name, c->pid,
c->setup.u.us.sock);
snprintf(r->response, NAME_MAX, "%s-response-%d-%d", s->name, c->pid,
c->setup.u.us.sock);
snprintf(r->event, NAME_MAX, "%s-event-%d-%d", s->name, c->pid,
c->setup.u.us.sock);
snprintf(r->request, NAME_MAX, "%s-request-%s",
s->name, c->description);
snprintf(r->response, NAME_MAX, "%s-response-%s",
s->name, c->description);
snprintf(r->event, NAME_MAX, "%s-event-%s",
s->name, c->description);
c->request.u.shm.rb = qb_rb_open(r->request,
c->request.max_msg_size,
QB_RB_FLAG_CREATE |
QB_RB_FLAG_SHARED_PROCESS,
sizeof(int32_t));
if (c->request.u.shm.rb == NULL) {
res = -errno;
qb_util_perror(LOG_ERR, "qb_rb_open:REQUEST");
goto cleanup;
}
res = qb_rb_chown(c->request.u.shm.rb, c->euid, c->egid);
res = qb_ipcs_shm_rb_open(c, &c->request,
r->request);
if (res != 0) {
qb_util_perror(LOG_ERR, "qb_rb_chown:REQUEST");
goto cleanup;
}
c->response.u.shm.rb = qb_rb_open(r->response,
c->response.max_msg_size,
QB_RB_FLAG_CREATE |
QB_RB_FLAG_SHARED_PROCESS, 0);
if (c->response.u.shm.rb == NULL) {
res = -errno;
qb_util_perror(LOG_ERR, "qb_rb_open:RESPONSE");
goto cleanup_request;
}
res = qb_rb_chown(c->response.u.shm.rb, c->euid, c->egid);
res = qb_ipcs_shm_rb_open(c, &c->response,
r->response);
if (res != 0) {
qb_util_perror(LOG_ERR, "qb_rb_chown:RESPONSE");
goto cleanup_request;
}
c->event.u.shm.rb = qb_rb_open(r->event,
c->event.max_msg_size,
QB_RB_FLAG_CREATE |
QB_RB_FLAG_SHARED_PROCESS, 0);
if (c->event.u.shm.rb == NULL) {
res = -errno;
qb_util_perror(LOG_ERR, "qb_rb_open:EVENT");
res = qb_ipcs_shm_rb_open(c, &c->event,
r->event);
if (res != 0) {
goto cleanup_request_response;
}
res = qb_rb_chown(c->event.u.shm.rb, c->euid, c->egid);
if (res != 0) {
qb_util_perror(LOG_ERR, "qb_rb_chown:EVENT");
goto cleanup_all;
}
r->hdr.error = 0;
return 0;
cleanup_all:
qb_rb_close(c->event.u.shm.rb);
cleanup_request_response:
qb_rb_close(c->request.u.shm.rb);

View File

@ -1,394 +0,0 @@
/*
* Copyright (C) 2010 Red Hat, Inc.
*
* Author: Angus Salkeld <asalkeld@redhat.com>
*
* This file is part of libqb.
*
* libqb 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.
*
* libqb 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 libqb. If not, see <http://www.gnu.org/licenses/>.
*/
#include "os_base.h"
#ifdef HAVE_SYS_IPC_H
#include <sys/ipc.h>
#endif
#ifdef HAVE_SYS_MSG_H
#include <sys/msg.h>
#endif
#include <qb/qbdefs.h>
#include <qb/qbloop.h>
#include "ipc_int.h"
#include "util_int.h"
#ifndef MSGMAX
#define MSGMAX 8192
#endif
#define MY_DATA_SIZE 8000
struct my_msgbuf {
int32_t id __attribute__ ((aligned(8)));
char data[MY_DATA_SIZE] __attribute__ ((aligned(8)));
} __attribute__ ((aligned(8)));
/*
* utility functions
* --------------------------------------------------------
*/
static int32_t
sysv_mq_unnamed_create(struct qb_ipcs_connection *c,
struct qb_ipc_one_way *queue)
{
struct msqid_ds info;
int32_t res = 0;
retry_creating_the_q:
queue->u.smq.key = random();
queue->u.smq.q =
msgget(queue->u.smq.key,
IPC_CREAT | IPC_EXCL | IPC_NOWAIT | S_IWUSR | S_IRUSR);
if (queue->u.smq.q == -1 && errno == EEXIST) {
goto retry_creating_the_q;
} else if (queue->u.smq.q == -1) {
return -errno;
}
/*
* change the queue size and change the ownership to that of
* the client so they can access it.
*/
res = msgctl(queue->u.smq.q, IPC_STAT, &info);
if (res != 0) {
res = -errno;
qb_util_perror(LOG_ERR, "error getting sysv-mq info");
return res;
}
if (info.msg_perm.uid != 0) {
qb_util_log(LOG_WARNING,
"not enough privileges to increase msg_qbytes");
return res;
}
info.msg_qbytes = 2 * queue->max_msg_size;
info.msg_perm.uid = c->euid;
info.msg_perm.gid = c->egid;
res = msgctl(queue->u.smq.q, IPC_SET, &info);
if (res != 0) {
res = -errno;
qb_util_perror(LOG_ERR,
"error modifying the SYSV message queue");
return res;
}
return 0;
}
static int32_t
sysv_split_and_send(int32_t q, const void *msg_ptr,
size_t msg_len, int32_t last_chunk)
{
int32_t res;
int32_t sent = 0;
#ifdef PACK_MESSAGES
char *progress = (char *)msg_ptr;
struct my_msgbuf buf;
size_t to_send_now; /* to send in this message */
size_t to_send_next; /* to send in next message */
do {
to_send_now = QB_MIN(msg_len - sent, MY_DATA_SIZE);
to_send_next = msg_len - (sent + to_send_now);
/* receiver used the ID to check to see if there
* is more to receive for this message.
*/
if (last_chunk) {
buf.id = to_send_next + 1;
} else {
buf.id = to_send_next + 1 + msg_len;
}
memcpy(buf.data, progress, to_send_now);
res = msgsnd(q, &buf, to_send_now, IPC_NOWAIT);
if (res == 0) {
sent += to_send_now;
progress += to_send_now;
} else {
goto return_status;
}
} while (sent < msg_len);
return_status:
#else
res = msgsnd(q, msg_ptr, msg_len, IPC_NOWAIT);
sent = msg_len;
#endif
if (res == -1) {
return -errno;
}
return sent;
}
/*
* client functions
* --------------------------------------------------------
*/
static ssize_t
qb_ipc_smq_send(struct qb_ipc_one_way *one_way,
const void *msg_ptr, size_t msg_len)
{
return sysv_split_and_send(one_way->u.smq.q, msg_ptr, msg_len, QB_TRUE);
}
static ssize_t
qb_ipc_smq_sendv(struct qb_ipc_one_way *one_way,
const struct iovec *iov, size_t iov_len)
{
int32_t res;
int32_t sent = 0;
struct my_msgbuf buf;
int32_t i;
for (i = 0; i < iov_len; i++) {
if (iov[i].iov_len <= MY_DATA_SIZE) {
if (i == iov_len - 1) {
buf.id = 1;
} else {
buf.id = i + iov[i].iov_len;
}
memcpy(buf.data, iov[i].iov_base, iov[i].iov_len);
res = msgsnd(one_way->u.smq.q,
&buf, iov[i].iov_len,
IPC_NOWAIT);
if (res == 0) {
res = iov[i].iov_len;
} else {
res = -errno;
}
} else {
res = sysv_split_and_send(one_way->u.smq.q,
iov[i].iov_base,
iov[i].iov_len,
(i == iov_len - 1));
}
if (res > 0) {
sent += res;
} else {
return res;
}
}
return sent;
}
static ssize_t
qb_ipc_smq_recv(struct qb_ipc_one_way *one_way,
void *msg_ptr, size_t msg_len, int32_t ms_timeout)
{
ssize_t res;
ssize_t received = 0;
#ifdef PACK_MESSAGES
char *progress = (char *)msg_ptr;
struct my_msgbuf buf;
do {
try_again:
res = msgrcv(one_way->u.smq.q, &buf,
MY_DATA_SIZE, 0, IPC_NOWAIT);
if (res == -1 && errno == ENOMSG) {
goto try_again;
}
//printf("res:%zd, ID:%d\n", res, buf.id);
if (res == -1) {
goto return_status;
}
memcpy(progress, buf.data, res);
received += res;
progress += res;
} while (buf.id > 1);
return_status:
#else
res = msgrcv(one_way->u.smq.q, msg_ptr, msg_len, 0, IPC_NOWAIT);
received = res;
#endif
if (res == -1 && errno == ENOMSG) {
/* just to be consistent with other IPC types.
*/
return -EAGAIN;
}
if (res == -1) {
perror(__func__);
return -errno;
}
return received;
}
static void
qb_ipcc_smq_disconnect(struct qb_ipcc_connection *c)
{
struct qb_ipc_request_header hdr;
qb_util_log(LOG_TRACE, "%s()", __func__);
hdr.id = QB_IPC_MSG_DISCONNECT;
hdr.size = sizeof(hdr);
(void)sysv_split_and_send(c->request.u.smq.q,
(const char *)&hdr, hdr.size, QB_TRUE);
msgctl(c->event.u.smq.q, IPC_RMID, NULL);
msgctl(c->response.u.smq.q, IPC_RMID, NULL);
msgctl(c->request.u.smq.q, IPC_RMID, NULL);
}
int32_t
qb_ipcc_smq_connect(struct qb_ipcc_connection *c,
struct qb_ipc_connection_response *response)
{
int32_t res = 0;
c->funcs.send = qb_ipc_smq_send;
c->funcs.sendv = qb_ipc_smq_sendv;
c->funcs.recv = qb_ipc_smq_recv;
c->funcs.fc_get = NULL;
c->funcs.disconnect = qb_ipcc_smq_disconnect;
c->needs_sock_for_poll = QB_TRUE;
if (strlen(c->name) > (NAME_MAX - 20)) {
return -EINVAL;
}
memcpy(&c->request.u.smq.key, response->request, sizeof(uint32_t));
c->request.u.smq.q = msgget(c->request.u.smq.key, IPC_NOWAIT);
if (c->request.u.smq.q == -1) {
res = -errno;
perror("msgget:REQUEST");
goto cleanup;
}
memcpy(&c->response.u.smq.key, response->response, sizeof(uint32_t));
c->response.u.smq.q = msgget(c->response.u.smq.key, IPC_NOWAIT);
if (c->response.u.smq.q == -1) {
res = -errno;
perror("msgget:RESPONSE");
goto cleanup_request;
}
memcpy(&c->event.u.smq.key, response->event, sizeof(uint32_t));
c->event.u.smq.q = msgget(c->event.u.smq.key, IPC_NOWAIT);
if (c->event.u.smq.q == -1) {
res = -errno;
perror("msgget:EVENT");
goto cleanup_request_response;
}
return 0;
cleanup_request_response:
msgctl(c->response.u.smq.q, IPC_RMID, NULL);
cleanup_request:
msgctl(c->request.u.smq.q, IPC_RMID, NULL);
cleanup:
return res;
}
/*
* service functions
* --------------------------------------------------------
*/
static void
qb_ipcs_smq_disconnect(struct qb_ipcs_connection *c)
{
struct qb_ipc_response_header msg;
if (c->setup.u.us.sock != -1) {
msg.id = QB_IPC_MSG_DISCONNECT;
msg.size = sizeof(msg);
msg.error = 0;
(void)qb_ipc_smq_send(&c->event, &msg, msg.size);
} else {
msgctl(c->event.u.smq.q, IPC_RMID, NULL);
msgctl(c->response.u.smq.q, IPC_RMID, NULL);
msgctl(c->request.u.smq.q, IPC_RMID, NULL);
}
}
static int32_t
qb_ipcs_smq_connect(struct qb_ipcs_service *s,
struct qb_ipcs_connection *c,
struct qb_ipc_connection_response *r)
{
int32_t res = 0;
res = sysv_mq_unnamed_create(c, &c->request);
if (res < 0) {
res = -errno;
goto cleanup;
}
memcpy(r->request, &c->request.u.smq.key, sizeof(int32_t));
res = sysv_mq_unnamed_create(c, &c->response);
if (res < 0) {
res = -errno;
goto cleanup_request;
}
memcpy(r->response, &c->response.u.smq.key, sizeof(int32_t));
res = sysv_mq_unnamed_create(c, &c->event);
if (res < 0) {
res = -errno;
goto cleanup_request_response;
}
memcpy(r->event, &c->event.u.smq.key, sizeof(int32_t));
r->hdr.error = 0;
return 0;
cleanup_request_response:
msgctl(c->response.u.smq.q, IPC_RMID, NULL);
cleanup_request:
msgctl(c->request.u.smq.q, IPC_RMID, NULL);
cleanup:
r->hdr.error = res;
return res;
}
static ssize_t
qb_ipc_smq_q_len_get(struct qb_ipc_one_way *one_way)
{
struct msqid_ds info;
int32_t res = msgctl(one_way->u.smq.q, IPC_STAT, &info);
if (res == 0) {
return info.msg_qnum;
}
return -errno;
}
void
qb_ipcs_smq_init(struct qb_ipcs_service *s)
{
s->funcs.connect = qb_ipcs_smq_connect;
s->funcs.disconnect = qb_ipcs_smq_disconnect;
s->funcs.send = qb_ipc_smq_send;
s->funcs.sendv = qb_ipc_smq_sendv;
s->funcs.recv = qb_ipc_smq_recv;
s->funcs.peek = NULL;
s->funcs.reclaim = NULL;
s->funcs.fc_set = NULL;
s->funcs.q_len_get = qb_ipc_smq_q_len_get;
s->needs_sock_for_poll = QB_TRUE;
}

View File

@ -48,16 +48,22 @@
#define UNIX_PATH_MAX 108
#endif /* UNIX_PATH_MAX */
#if defined(QB_LINUX) || defined(QB_SOLARIS)
#define QB_SUN_LEN(a) sizeof(*(a))
/*
* SUN_LEN() does a strlen() on sun_path, but if you are trying to use the
* "Linux abstract namespace" (you have to set sun_path[0] == '\0') then
* the strlen() doesn't work.
*/
#if defined(SUN_LEN)
#define QB_SUN_LEN(a) ((a)->sun_path[0] == '\0') ? sizeof(*(a)) : SUN_LEN(a)
#else
#define QB_SUN_LEN(a) SUN_LEN(a)
#define QB_SUN_LEN(a) sizeof(*(a))
#endif
struct ipc_us_control {
int32_t sent;
int32_t flow_control;
};
#define SHM_CONTROL_SIZE (3 * sizeof(struct ipc_us_control))
struct ipc_auth_ugp {
uid_t uid;
@ -85,33 +91,21 @@ ssize_t
qb_ipc_us_send(struct qb_ipc_one_way *one_way, const void *msg, size_t len)
{
int32_t result;
struct msghdr msg_send;
struct iovec iov_send;
char *rbuf = (char *)msg;
int32_t processed = 0;
struct ipc_us_control *ctl = NULL;
msg_send.msg_iov = &iov_send;
msg_send.msg_iovlen = 1;
msg_send.msg_name = 0;
msg_send.msg_namelen = 0;
#if !defined(QB_SOLARIS)
msg_send.msg_control = 0;
msg_send.msg_controllen = 0;
msg_send.msg_flags = 0;
#else
msg_send.msg_accrights = NULL;
msg_send.msg_accrightslen = 0;
#endif
char *rbuf = (char *)msg;
retry_send:
iov_send.iov_base = &rbuf[processed];
iov_send.iov_len = len - processed;
result = send(one_way->u.us.sock,
&rbuf[processed],
len - processed,
MSG_NOSIGNAL);
result = sendmsg(one_way->u.us.sock, &msg_send, MSG_NOSIGNAL);
if (result == -1) {
return -errno;
if (errno == EAGAIN && processed > 0) {
goto retry_send;
} else {
return -errno;
}
}
processed += result;
@ -119,6 +113,7 @@ retry_send:
goto retry_send;
}
if (one_way->type == QB_IPC_SOCKET) {
struct ipc_us_control *ctl = NULL;
ctl = (struct ipc_us_control *)one_way->u.us.shared_data;
if (ctl) {
qb_atomic_int_inc(&ctl->sent);
@ -132,46 +127,46 @@ qb_ipc_us_sendv(struct qb_ipc_one_way *one_way, const struct iovec *iov,
size_t iov_len)
{
int32_t result;
struct msghdr msg_send;
int32_t processed = 0;
size_t len = 0;
int32_t i;
struct ipc_us_control *ctl = NULL;
for (i = 0; i < iov_len; i++) {
len += iov[i].iov_len;
}
msg_send.msg_iov = (struct iovec *)iov;
msg_send.msg_iovlen = iov_len;
msg_send.msg_name = 0;
msg_send.msg_namelen = 0;
#if !defined(QB_SOLARIS)
msg_send.msg_control = 0;
msg_send.msg_controllen = 0;
msg_send.msg_flags = 0;
#else
msg_send.msg_accrights = NULL;
msg_send.msg_accrightslen = 0;
#endif
int32_t total_processed = 0;
int32_t iov_p = 0;
char *rbuf = (char *)iov[iov_p].iov_base;
retry_send:
result = sendmsg(one_way->u.us.sock, &msg_send, MSG_NOSIGNAL);
result = send(one_way->u.us.sock,
&rbuf[processed],
iov[iov_p].iov_len - processed,
MSG_NOSIGNAL);
if (result == -1) {
return -errno;
if (errno == EAGAIN &&
(processed > 0 || iov_p > 0)) {
goto retry_send;
} else {
return -errno;
}
}
processed += result;
if (processed != len) {
if (processed == iov[iov_p].iov_len) {
iov_p++;
total_processed += processed;
if (iov_p < iov_len) {
processed = 0;
rbuf = (char *)iov[iov_p].iov_base;
goto retry_send;
}
} else {
goto retry_send;
}
if (one_way->type == QB_IPC_SOCKET) {
struct ipc_us_control *ctl;
ctl = (struct ipc_us_control *)one_way->u.us.shared_data;
if (ctl) {
qb_atomic_int_inc(&ctl->sent);
}
}
return processed;
return total_processed;
}
static ssize_t
@ -191,14 +186,11 @@ retry_recv:
if (result == -1) {
return -errno;
}
#if defined(QB_SOLARIS) || defined(QB_BSD) || defined(QB_DARWIN)
/* On many OS poll never return POLLHUP or POLLERR.
* EOF is detected when recvmsg return 0.
*/
if (result == 0) {
return -errno; //ENOTCONN
qb_util_log(LOG_DEBUG,
"recv(fd %d) got 0 bytes assuming ENOTCONN", s);
return -ENOTCONN;
}
#endif
processed += result;
if (processed != len) {
@ -210,13 +202,29 @@ retry_recv:
}
int32_t
qb_ipc_us_recv_ready(struct qb_ipc_one_way * one_way, int32_t ms_timeout)
qb_ipc_us_sock_error_is_disconnected(int err)
{
if (err == -EAGAIN ||
err == -ETIMEDOUT ||
err == -EINTR ||
#ifdef EWOULDBLOCK
err == -EWOULDBLOCK ||
#endif
err == -EINVAL) {
return QB_FALSE;
}
return QB_TRUE;
}
int32_t
qb_ipc_us_ready(struct qb_ipc_one_way * one_way,
int32_t ms_timeout, int32_t events)
{
struct pollfd ufds;
int32_t poll_events;
ufds.fd = one_way->u.us.sock;
ufds.events = POLLIN;
ufds.events = events;
ufds.revents = 0;
poll_events = poll(&ufds, 1, ms_timeout);
@ -224,7 +232,14 @@ qb_ipc_us_recv_ready(struct qb_ipc_one_way * one_way, int32_t ms_timeout)
return -EAGAIN;
} else if (poll_events == -1) {
return -errno;
} else if (poll_events == 1 && (ufds.revents & (POLLERR | POLLHUP))) {
} else if (poll_events == 1 && (ufds.revents & POLLERR)) {
qb_util_log(LOG_DEBUG, "poll(fd %d) got POLLERR", one_way->u.us.sock);
return -ENOTCONN;
} else if (poll_events == 1 && (ufds.revents & POLLHUP)) {
qb_util_log(LOG_DEBUG, "poll(fd %d) got POLLHUP", one_way->u.us.sock);
return -ENOTCONN;
} else if (poll_events == 1 && (ufds.revents & POLLNVAL)) {
qb_util_log(LOG_DEBUG, "poll(fd %d) got POLLNVAL", one_way->u.us.sock);
return -ENOTCONN;
}
return 0;
@ -241,27 +256,38 @@ qb_ipc_us_recv(struct qb_ipc_one_way * one_way,
int32_t processed = 0;
int32_t to_recv = len;
char *data = msg;
struct ipc_us_control *ctl = NULL;
retry_recv:
result = recv(one_way->u.us.sock, &data[processed], to_recv, MSG_NOSIGNAL | MSG_WAITALL);
if (timeout == -1) {
if (result == -1 && errno == EAGAIN) {
result = recv(one_way->u.us.sock, &data[processed], to_recv,
MSG_NOSIGNAL | MSG_WAITALL);
if (result == -1) {
if (errno == EAGAIN &&
(processed > 0 || timeout == -1)) {
goto retry_recv;
} else if (errno == ECONNRESET || errno == EPIPE) {
qb_util_perror(LOG_DEBUG,
"recv(fd %d) converting to ENOTCONN",
one_way->u.us.sock);
return -ENOTCONN;
} else {
return -errno;
}
}
if (result == 0) {
qb_util_log(LOG_DEBUG,
"recv(fd %d) got 0 bytes assuming ENOTCONN",
one_way->u.us.sock);
return -ENOTCONN;
}
if (result == -1) {
return -errno;
}
processed += result;
to_recv -= result;
if (processed != len) {
goto retry_recv;
}
if (one_way->type == QB_IPC_SOCKET) {
struct ipc_us_control *ctl = NULL;
ctl = (struct ipc_us_control *)one_way->u.us.shared_data;
if (ctl) {
(void)qb_atomic_int_dec_and_test(&ctl->sent);
@ -271,34 +297,53 @@ retry_recv:
}
/*
* recv a message of unknow size.
* (could use MSG_PEEK here)
* recv a message of unknown size.
*/
static ssize_t
qb_ipc_us_recv_at_most(struct qb_ipc_one_way * one_way,
void *msg, size_t len, int32_t timeout)
{
int32_t result;
int32_t processed = 0;
int32_t to_recv = sizeof(struct qb_ipc_request_header);
char *data = msg;
struct ipc_us_control *ctl = NULL;
struct qb_ipc_request_header *hdr = NULL;
retry_recv:
result = recv(one_way->u.us.sock, msg, len, MSG_NOSIGNAL | MSG_WAITALL);
if (timeout == -1) {
if (result == -1 && errno == EAGAIN) {
result = recv(one_way->u.us.sock, &data[processed], to_recv,
MSG_NOSIGNAL | MSG_WAITALL);
if (result == -1) {
if (errno == EAGAIN &&
(processed > 0 || timeout == -1)) {
goto retry_recv;
} else {
return -errno;
}
}
if (result == 0) {
} else if (result == 0) {
qb_util_log(LOG_DEBUG,
"recv(fd %d) got 0 bytes assuming ENOTCONN",
one_way->u.us.sock);
return -ENOTCONN;
}
if (result == -1) {
return -errno;
processed += result;
if (processed >= sizeof(struct qb_ipc_request_header) && hdr == NULL) {
hdr = (struct qb_ipc_request_header*)msg;
}
if (hdr) {
to_recv = hdr->size - processed;
} else {
to_recv = len - processed;
}
if (to_recv > 0) {
goto retry_recv;
}
ctl = (struct ipc_us_control *)one_way->u.us.shared_data;
if (ctl) {
(void)qb_atomic_int_dec_and_test(&ctl->sent);
}
return result;
return processed;
}
@ -309,11 +354,7 @@ qb_ipcc_us_sock_connect(const char *socket_name, int32_t * sock_pt)
struct sockaddr_un address;
int32_t res = 0;
#if defined(QB_SOLARIS)
request_fd = socket(PF_UNIX, SOCK_STREAM, 0);
#else
request_fd = socket(PF_LOCAL, SOCK_STREAM, 0);
#endif
if (request_fd == -1) {
return -errno;
}
@ -327,11 +368,11 @@ qb_ipcc_us_sock_connect(const char *socket_name, int32_t * sock_pt)
memset(&address, 0, sizeof(struct sockaddr_un));
address.sun_family = AF_UNIX;
#if defined(QB_BSD) || defined(QB_DARWIN)
address.sun_len = SUN_LEN(&address);
#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
address.sun_len = QB_SUN_LEN(&address);
#endif
#if defined(QB_LINUX)
#if defined(QB_LINUX) || defined(QB_CYGWIN)
snprintf(address.sun_path + 1, UNIX_PATH_MAX - 1, "%s", socket_name);
#else
snprintf(address.sun_path, UNIX_PATH_MAX, "%s/%s", SOCKETDIR,
@ -366,12 +407,21 @@ qb_ipcc_us_setup_connect(struct qb_ipcc_connection *c,
{
int32_t res;
struct qb_ipc_connection_request request;
#ifdef QB_LINUX
int off = 0;
int on = 1;
#endif
res = qb_ipcc_us_sock_connect(c->name, &c->setup.u.us.sock);
if (res != 0) {
return res;
}
#ifdef QB_LINUX
setsockopt(c->setup.u.us.sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
#endif
memset(&request, 0, sizeof(request));
request.hdr.id = QB_IPC_MSG_AUTHENTICATE;
request.hdr.size = sizeof(request);
request.max_msg_size = c->setup.max_msg_size;
@ -381,6 +431,10 @@ qb_ipcc_us_setup_connect(struct qb_ipcc_connection *c,
return res;
}
#ifdef QB_LINUX
setsockopt(c->setup.u.us.sock, SOL_SOCKET, SO_PASSCRED, &off, sizeof(off));
#endif
res =
qb_ipc_us_recv(&c->setup, r,
sizeof(struct qb_ipc_connection_response), -1);
@ -397,7 +451,7 @@ qb_ipcc_us_setup_connect(struct qb_ipcc_connection *c,
static void
qb_ipcc_us_disconnect(struct qb_ipcc_connection *c)
{
munmap(c->request.u.us.shared_data, sizeof(struct ipc_us_control));
munmap(c->request.u.us.shared_data, SHM_CONTROL_SIZE);
unlink(c->request.u.us.shared_file_name);
close(c->request.u.us.sock);
close(c->event.u.us.sock);
@ -411,7 +465,7 @@ qb_ipcc_us_connect(struct qb_ipcc_connection *c,
struct qb_ipc_event_connection_request request;
char path[PATH_MAX];
int32_t fd_hdr;
struct ipc_us_control *ctl;
char * shm_ptr;
c->needs_sock_for_poll = QB_FALSE;
c->funcs.send = qb_ipc_us_send;
@ -425,27 +479,24 @@ qb_ipcc_us_connect(struct qb_ipcc_connection *c,
c->setup.u.us.sock = -1;
fd_hdr = qb_sys_mmap_file_open(path, r->request,
sizeof(struct ipc_us_control), O_RDWR);
SHM_CONTROL_SIZE, O_RDWR);
if (fd_hdr < 0) {
res = -errno;
qb_util_perror(LOG_ERR, "couldn't open file for mmap");
return res;
}
(void)strlcpy(c->request.u.us.shared_file_name, r->request, NAME_MAX);
c->request.u.us.shared_data = mmap(0,
sizeof(struct ipc_us_control),
PROT_READ | PROT_WRITE, MAP_SHARED,
fd_hdr, 0);
shm_ptr = mmap(0, SHM_CONTROL_SIZE,
PROT_READ | PROT_WRITE, MAP_SHARED, fd_hdr, 0);
if (c->request.u.us.shared_data == MAP_FAILED) {
if (shm_ptr == MAP_FAILED) {
res = -errno;
qb_util_perror(LOG_ERR, "couldn't create mmap for header");
goto cleanup_hdr;
}
ctl = (struct ipc_us_control *)c->request.u.us.shared_data;
ctl->sent = 0;
ctl->flow_control = 0;
c->request.u.us.shared_data = shm_ptr;
c->response.u.us.shared_data = shm_ptr + sizeof(struct ipc_us_control);
c->event.u.us.shared_data = shm_ptr + (2 * sizeof(struct ipc_us_control));
close(fd_hdr);
@ -454,13 +505,14 @@ qb_ipcc_us_connect(struct qb_ipcc_connection *c,
goto cleanup_hdr;
}
memset(&request, 0, sizeof(request));
request.hdr.id = QB_IPC_MSG_NEW_EVENT_SOCK;
request.hdr.size = sizeof(request);
request.connection = r->connection;
res = qb_ipc_us_send(&c->event, &request, request.hdr.size);
if (res < 0) {
qb_ipcc_us_sock_close(c->event.u.us.sock);
return res;
goto cleanup_hdr;
}
return 0;
@ -468,7 +520,7 @@ qb_ipcc_us_connect(struct qb_ipcc_connection *c,
cleanup_hdr:
close(fd_hdr);
unlink(r->request);
munmap(c->request.u.us.shared_data, sizeof(struct ipc_us_control));
munmap(c->request.u.us.shared_data, SHM_CONTROL_SIZE);
return res;
}
@ -486,11 +538,7 @@ qb_ipcs_us_publish(struct qb_ipcs_service * s)
/*
* Create socket for IPC clients, name socket, listen for connections
*/
#if defined(QB_SOLARIS)
s->server_sock = socket(PF_UNIX, SOCK_STREAM, 0);
#else
s->server_sock = socket(PF_LOCAL, SOCK_STREAM, 0);
#endif
if (s->server_sock == -1) {
res = -errno;
qb_util_perror(LOG_ERR, "Cannot create server socket");
@ -509,7 +557,7 @@ qb_ipcs_us_publish(struct qb_ipcs_service * s)
#endif
qb_util_log(LOG_INFO, "server name: %s", s->name);
#if defined(QB_LINUX)
#if defined(QB_LINUX) || defined(QB_CYGWIN)
snprintf(un_addr.sun_path + 1, UNIX_PATH_MAX - 1, "%s", s->name);
#else
{
@ -541,7 +589,7 @@ qb_ipcs_us_publish(struct qb_ipcs_service * s)
* Allow everyone to write to the socket since the IPC layer handles
* security automatically
*/
#if !defined(QB_LINUX)
#if !defined(QB_LINUX) && !defined(QB_CYGWIN)
res = chmod(un_addr.sun_path, S_IRWXU | S_IRWXG | S_IRWXO);
#endif
if (listen(s->server_sock, SERVER_BACKLOG) == -1) {
@ -585,7 +633,7 @@ handle_new_connection(struct qb_ipcs_service *s,
return -ENOMEM;
}
c->receive_buf = malloc(req->max_msg_size);
c->receive_buf = calloc(1, req->max_msg_size);
if (c->receive_buf == NULL) {
free(c);
qb_ipcc_us_sock_close(sock);
@ -596,9 +644,13 @@ handle_new_connection(struct qb_ipcs_service *s,
c->response.max_msg_size = req->max_msg_size;
c->event.max_msg_size = req->max_msg_size;
c->pid = ugp->pid;
c->euid = ugp->uid;
c->egid = ugp->gid;
c->auth.uid = c->euid = ugp->uid;
c->auth.gid = c->egid = ugp->gid;
c->auth.mode = 0600;
c->stats.client_pid = ugp->pid;
snprintf(c->description, CONNECTION_DESCRIPTION,
"%d-%d-%d", s->pid, ugp->pid,
c->setup.u.us.sock);
if (auth_result == 0 && c->service->serv_fns.connection_accept) {
res = c->service->serv_fns.connection_accept(c,
@ -608,7 +660,8 @@ handle_new_connection(struct qb_ipcs_service *s,
goto send_response;
}
qb_util_log(LOG_INFO, "IPC credentials authenticated");
qb_util_log(LOG_DEBUG, "IPC credentials authenticated (%s)",
c->description);
memset(&response, 0, sizeof(response));
if (s->funcs.connect) {
@ -630,19 +683,15 @@ handle_new_connection(struct qb_ipcs_service *s,
POLLIN | POLLPRI | POLLNVAL,
c,
qb_ipcs_dispatch_connection_request);
if (res < 0) {
qb_util_log(LOG_ERR,
"Error adding socket to mainloop (%s).",
c->description);
}
}
if (s->type == QB_IPC_SOCKET) {
c->request.u.us.sock = c->setup.u.us.sock;
c->response.u.us.sock = c->setup.u.us.sock;
res = s->poll_fns.dispatch_add(s->poll_priority,
c->request.u.us.sock,
POLLIN | POLLPRI | POLLNVAL,
c,
qb_ipcs_dispatch_connection_request);
if (res < 0) {
qb_util_log(LOG_ERR,
"Error adding socket to mainloop.");
}
}
send_response:
@ -662,19 +711,24 @@ send_response:
}
if (res == 0) {
qb_ipcs_connection_ref(c);
if (s->serv_fns.connection_created) {
s->serv_fns.connection_created(c);
if (s->type != QB_IPC_SOCKET) {
qb_ipcs_connection_ref(c);
if (s->serv_fns.connection_created) {
s->serv_fns.connection_created(c);
}
if (c->state == QB_IPCS_CONNECTION_ACTIVE) {
c->state = QB_IPCS_CONNECTION_ESTABLISHED;
}
qb_ipcs_connection_unref(c);
}
if (c->state == QB_IPCS_CONNECTION_ACTIVE) {
c->state = QB_IPCS_CONNECTION_ESTABLISHED;
}
qb_ipcs_connection_unref(c);
} else {
if (res == -EACCES) {
qb_util_log(LOG_ERR, "Invalid IPC credentials.");
qb_util_log(LOG_ERR, "Invalid IPC credentials (%s).",
c->description);
} else {
qb_util_perror(LOG_ERR, "Error in connection setup");
errno = -res;
qb_util_perror(LOG_ERR, "Error in connection setup (%s)",
c->description);
}
qb_ipcs_disconnect(c);
}
@ -688,7 +742,32 @@ handle_connection_new_sock(struct qb_ipcs_service *s, int32_t sock, void *msg)
struct qb_ipc_event_connection_request *req = msg;
c = (struct qb_ipcs_connection *)req->connection;
qb_ipcs_connection_ref(c);
c->event.u.us.sock = sock;
if (c->state == QB_IPCS_CONNECTION_ACTIVE) {
c->state = QB_IPCS_CONNECTION_ESTABLISHED;
}
if (s->serv_fns.connection_created) {
s->serv_fns.connection_created(c);
}
if (c->state == QB_IPCS_CONNECTION_ESTABLISHED &&
s->type == QB_IPC_SOCKET) {
int32_t res;
qb_ipcs_connection_ref(c);
res = s->poll_fns.dispatch_add(s->poll_priority,
c->request.u.us.sock,
POLLIN | POLLPRI | POLLNVAL,
c,
qb_ipcs_dispatch_connection_request);
if (res < 0) {
qb_util_log(LOG_ERR,
"Error adding socket to mainloop (%s).",
c->description);
}
}
qb_ipcs_connection_unref(c);
}
static int32_t
@ -699,28 +778,29 @@ qb_ipcs_uc_recv_and_auth(int32_t sock, void *msg, size_t len,
struct msghdr msg_recv;
struct iovec iov_recv;
#ifdef QB_LINUX
#ifdef SO_PASSCRED
char cmsg_cred[CMSG_SPACE(sizeof(struct ucred))];
int off = 0;
int on = 1;
#endif
msg_recv.msg_flags = 0;
msg_recv.msg_iov = &iov_recv;
msg_recv.msg_iovlen = 1;
msg_recv.msg_name = 0;
msg_recv.msg_namelen = 0;
#ifdef QB_LINUX
#ifdef SO_PASSCRED
msg_recv.msg_control = (void *)cmsg_cred;
msg_recv.msg_controllen = sizeof(cmsg_cred);
#endif
#ifdef QB_SOLARIS
msg_recv.msg_accrights = 0;
msg_recv.msg_accrightslen = 0;
#else
msg_recv.msg_flags = 0;
#endif /* QB_SOLARIS */
iov_recv.iov_base = msg;
iov_recv.iov_len = len;
#ifdef QB_LINUX
#ifdef SO_PASSCRED
setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
#endif
@ -776,16 +856,19 @@ qb_ipcs_uc_recv_and_auth(int32_t sock, void *msg, size_t len,
*/
{
struct ucred cred;
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg_recv);
assert(cmsg != NULL);
if (CMSG_DATA(cmsg)) {
struct cmsghdr *cmsg;
res = -EINVAL;
for (cmsg = CMSG_FIRSTHDR(&msg_recv); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg_recv, cmsg)) {
if (cmsg->cmsg_type != SCM_CREDENTIALS)
continue;
memcpy(&cred, CMSG_DATA(cmsg), sizeof(struct ucred));
res = 0;
ugp->pid = cred.pid;
ugp->uid = cred.uid;
ugp->gid = cred.gid;
} else {
res = -EBADMSG;
break;
}
}
#else /* no credentials */
@ -797,7 +880,7 @@ qb_ipcs_uc_recv_and_auth(int32_t sock, void *msg, size_t len,
cleanup_and_return:
#ifdef QB_LINUX
#ifdef SO_PASSCRED
setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &off, sizeof(off));
#endif
@ -815,6 +898,13 @@ qb_ipcs_us_connection_acceptor(int fd, int revent, void *data)
struct ipc_auth_ugp ugp;
socklen_t addrlen = sizeof(struct sockaddr_un);
if (revent & (POLLNVAL|POLLHUP|POLLERR)) {
/*
* handle shutdown more cleanly.
*/
return -1;
}
retry_accept:
errno = 0;
new_fd = accept(fd, (struct sockaddr *)&un_addr, &addrlen);
@ -847,6 +937,13 @@ retry_accept:
res = qb_ipcs_uc_recv_and_auth(new_fd, &setup_msg, sizeof(setup_msg),
&ugp);
if (res < 0) {
close(new_fd);
/* This is an error, but -1 would indicate disconnect
* from the poll loop
*/
return 0;
}
if (setup_msg.hdr.id == QB_IPC_MSG_AUTHENTICATE) {
(void)handle_new_connection(s, res, new_fd, &setup_msg,
@ -873,37 +970,60 @@ qb_ipcs_us_connect(struct qb_ipcs_service *s,
int32_t fd_hdr;
int32_t res = 0;
struct ipc_us_control *ctl;
char * shm_ptr;
qb_util_log(LOG_DEBUG, "connecting to client [%d]", c->pid);
qb_util_log(LOG_DEBUG, "connecting to client (%s)",
c->description);
snprintf(r->request, NAME_MAX, "qb-%s-control-%d-%d",
s->name, c->pid, c->setup.u.us.sock);
snprintf(r->request, NAME_MAX, "qb-%s-control-%s",
s->name, c->description);
fd_hdr = qb_sys_mmap_file_open(path, r->request,
sizeof(struct ipc_us_control),
SHM_CONTROL_SIZE,
O_CREAT | O_TRUNC | O_RDWR);
if (fd_hdr < 0) {
res = -errno;
qb_util_perror(LOG_ERR, "couldn't create file for mmap");
qb_util_perror(LOG_ERR, "couldn't create file for mmap (%s)",
c->description);
return res;
}
(void)strlcpy(r->request, path, PATH_MAX);
(void)strlcpy(c->request.u.us.shared_file_name, r->request, NAME_MAX);
c->request.u.us.shared_data = mmap(0,
sizeof(struct ipc_us_control),
PROT_READ | PROT_WRITE, MAP_SHARED,
fd_hdr, 0);
if (c->request.u.us.shared_data == MAP_FAILED) {
res = -errno;
qb_util_perror(LOG_ERR, "couldn't create mmap for header");
goto cleanup_hdr;
res = chown(r->request, c->auth.uid, c->auth.gid);
if (res != 0) {
/* ignore res, this is just for the compiler warnings.
*/
res = 0;
}
res = chmod(r->request, c->auth.mode);
if (res != 0) {
/* ignore res, this is just for the compiler warnings.
*/
res = 0;
}
shm_ptr = mmap(0, SHM_CONTROL_SIZE,
PROT_READ | PROT_WRITE, MAP_SHARED, fd_hdr, 0);
if (shm_ptr == MAP_FAILED) {
res = -errno;
qb_util_perror(LOG_ERR, "couldn't create mmap for header (%s)",
c->description);
goto cleanup_hdr;
}
c->request.u.us.shared_data = shm_ptr;
c->response.u.us.shared_data = shm_ptr + sizeof(struct ipc_us_control);
c->event.u.us.shared_data = shm_ptr + (2 * sizeof(struct ipc_us_control));
ctl = (struct ipc_us_control *)c->request.u.us.shared_data;
ctl->sent = 0;
ctl->flow_control = 0;
ctl = (struct ipc_us_control *)c->response.u.us.shared_data;
ctl->sent = 0;
ctl->flow_control = 0;
ctl = (struct ipc_us_control *)c->event.u.us.shared_data;
ctl->sent = 0;
ctl->flow_control = 0;
close(fd_hdr);
return res;
@ -911,7 +1031,7 @@ qb_ipcs_us_connect(struct qb_ipcs_service *s,
cleanup_hdr:
close(fd_hdr);
unlink(r->request);
munmap(c->request.u.us.shared_data, sizeof(struct ipc_us_control));
munmap(c->request.u.us.shared_data, SHM_CONTROL_SIZE);
return res;
}
@ -921,7 +1041,8 @@ qb_ipc_us_fc_set(struct qb_ipc_one_way *one_way, int32_t fc_enable)
struct ipc_us_control *ctl =
(struct ipc_us_control *)one_way->u.us.shared_data;
qb_util_log(LOG_TRACE, "setting fc to %d", fc_enable);
qb_util_log(LOG_TRACE, "setting fc to %d",
fc_enable);
qb_atomic_int_set(&ctl->flow_control, fc_enable);
}
@ -942,14 +1063,35 @@ qb_ipc_us_q_len_get(struct qb_ipc_one_way *one_way)
return qb_atomic_int_get(&ctl->sent);
}
void
qb_ipcs_sockets_disconnect(struct qb_ipcs_connection *c)
{
int sock = -1;
qb_enter();
if (c->service->needs_sock_for_poll && c->setup.u.us.sock > 0) {
sock = c->setup.u.us.sock;
qb_ipcc_us_sock_close(sock);
c->setup.u.us.sock = -1;
}
if (c->request.type == QB_IPC_SOCKET) {
sock = c->request.u.us.sock;
}
if (sock > 0) {
(void)c->service->poll_fns.dispatch_del(sock);
qb_ipcs_connection_unref(c);
}
}
static void
qb_ipcs_us_disconnect(struct qb_ipcs_connection *c)
{
munmap(c->request.u.us.shared_data, sizeof(struct ipc_us_control));
qb_enter();
munmap(c->request.u.us.shared_data, SHM_CONTROL_SIZE);
unlink(c->request.u.us.shared_file_name);
close(c->request.u.us.sock);
close(c->event.u.us.sock);
qb_ipcc_us_sock_close(c->request.u.us.sock);
qb_ipcc_us_sock_close(c->event.u.us.sock);
}
void

View File

@ -20,9 +20,6 @@
*/
#include "os_base.h"
#ifdef HAVE_MQUEUE_H
#include <mqueue.h>
#endif /* HAVE_MQUEUE_H */
#include "ipc_int.h"
#include "util_int.h"
#include <qb/qbdefs.h>
@ -40,7 +37,8 @@ qb_ipcc_connect(const char *name, size_t max_msg_size)
return NULL;
}
c->setup.max_msg_size = max_msg_size;
c->setup.max_msg_size = QB_MAX(max_msg_size,
sizeof(struct qb_ipc_connection_response));
(void)strlcpy(c->name, name, NAME_MAX);
res = qb_ipcc_us_setup_connect(c, &response);
if (res < 0) {
@ -54,7 +52,7 @@ qb_ipcc_connect(const char *name, size_t max_msg_size)
c->response.max_msg_size = response.max_msg_size;
c->request.max_msg_size = response.max_msg_size;
c->event.max_msg_size = response.max_msg_size;
c->receive_buf = malloc(response.max_msg_size);
c->receive_buf = calloc(1, response.max_msg_size);
c->fc_enable_max = 1;
if (c->receive_buf == NULL) {
res = -ENOMEM;
@ -65,23 +63,13 @@ qb_ipcc_connect(const char *name, size_t max_msg_size)
case QB_IPC_SHM:
res = qb_ipcc_shm_connect(c, &response);
break;
case QB_IPC_POSIX_MQ:
#ifdef HAVE_POSIX_MQ
res = qb_ipcc_pmq_connect(c, &response);
#else
res = -ENOTSUP;
#endif /* HAVE_POSIX_MQ */
break;
case QB_IPC_SYSV_MQ:
#ifdef HAVE_SYSV_MQ
res = qb_ipcc_smq_connect(c, &response);
#else
res = -ENOTSUP;
#endif /* HAVE_SYSV_MQ */
break;
case QB_IPC_SOCKET:
res = qb_ipcc_us_connect(c, &response);
break;
case QB_IPC_POSIX_MQ:
case QB_IPC_SYSV_MQ:
res = -ENOTSUP;
break;
default:
res = -EINVAL;
break;
@ -100,6 +88,44 @@ disconnect_and_cleanup:
return NULL;
}
static void
_check_connection_state(struct qb_ipcc_connection * c, int32_t res)
{
if (res >= 0) return;
if (qb_ipc_us_sock_error_is_disconnected(res)) {
errno = -res;
qb_util_perror(LOG_DEBUG,
"interpreting result %d as a disconnect",
res);
c->is_connected = QB_FALSE;
}
}
static struct qb_ipc_one_way *
_event_sock_one_way_get(struct qb_ipcc_connection * c)
{
if (c->needs_sock_for_poll) {
return &c->setup;
}
if (c->event.type == QB_IPC_SOCKET) {
return &c->event;
}
return NULL;
}
static struct qb_ipc_one_way *
_response_sock_one_way_get(struct qb_ipcc_connection * c)
{
if (c->needs_sock_for_poll) {
return &c->setup;
}
if (c->response.type == QB_IPC_SOCKET) {
return &c->response;
}
return NULL;
}
ssize_t
qb_ipcc_send(struct qb_ipcc_connection * c, const void *msg_ptr, size_t msg_len)
{
@ -128,13 +154,13 @@ qb_ipcc_send(struct qb_ipcc_connection * c, const void *msg_ptr, size_t msg_len)
res2 = qb_ipc_us_send(&c->setup, msg_ptr, 1);
} while (res2 == -EAGAIN);
if (res2 == -EPIPE) {
c->is_connected = QB_FALSE;
return -ENOTCONN;
res2 = -ENOTCONN;
}
if (res2 != 1) {
res = res2;
}
}
_check_connection_state(c, res);
return res;
}
@ -183,13 +209,13 @@ qb_ipcc_sendv(struct qb_ipcc_connection * c, const struct iovec * iov,
res2 = qb_ipc_us_send(&c->setup, &res, 1);
} while (res2 == -EAGAIN);
if (res2 == -EPIPE) {
c->is_connected = QB_FALSE;
return -ENOTCONN;
res2 = -ENOTCONN;
}
if (res2 != 1) {
res = res2;
}
}
_check_connection_state(c, res);
return res;
}
@ -204,17 +230,17 @@ qb_ipcc_recv(struct qb_ipcc_connection * c, void *msg_ptr,
}
res = c->funcs.recv(&c->response, msg_ptr, msg_len, ms_timeout);
if ((res == -EAGAIN || res == -ETIMEDOUT) && c->needs_sock_for_poll) {
res2 = qb_ipc_us_recv_ready(&c->setup, 0);
if (res == -EAGAIN || res == -ETIMEDOUT) {
struct qb_ipc_one_way *ow = _response_sock_one_way_get(c);
if (ow == NULL) return res;
res2 = qb_ipc_us_ready(ow, 0, POLLIN);
if (res2 < 0) {
if (res2 == -ENOTCONN) {
c->is_connected = QB_FALSE;
}
return res2;
} else {
return res;
res = res2;
}
}
_check_connection_state(c, res);
return res;
}
@ -303,31 +329,23 @@ qb_ipcc_event_recv(struct qb_ipcc_connection * c, void *msg_pt,
if (c == NULL) {
return -EINVAL;
}
if (c->needs_sock_for_poll) {
ow = &c->setup;
}
if (c->event.type == QB_IPC_SOCKET) {
ow = &c->event;
}
ow = _event_sock_one_way_get(c);
if (ow) {
res = qb_ipc_us_recv_ready(ow, ms_timeout);
res = qb_ipc_us_ready(ow, ms_timeout, POLLIN);
if (res < 0) {
if (res == -ENOTCONN) {
c->is_connected = QB_FALSE;
}
_check_connection_state(c, res);
return res;
}
}
size = c->funcs.recv(&c->event, msg_pt, msg_len, ms_timeout);
if (size < 0) {
_check_connection_state(c, size);
return size;
}
if (c->needs_sock_for_poll) {
res = qb_ipc_us_recv(&c->setup, &one_byte, 1, -1);
if (res < 0) {
if (res == -ENOTCONN) {
c->is_connected = QB_FALSE;
}
_check_connection_state(c, res);
return res;
}
}
@ -338,6 +356,7 @@ void
qb_ipcc_disconnect(struct qb_ipcc_connection *c)
{
struct qb_ipc_one_way *ow = NULL;
int32_t res = 0;
qb_util_log(LOG_DEBUG, "%s()", __func__);
@ -345,19 +364,13 @@ qb_ipcc_disconnect(struct qb_ipcc_connection *c)
return;
}
if (c->needs_sock_for_poll) {
ow = &c->setup;
}
if (c->event.type == QB_IPC_SOCKET) {
ow = &c->event;
}
ow = _event_sock_one_way_get(c);
if (ow) {
if (qb_ipc_us_recv_ready(ow, 0) == -ENOTCONN) {
c->is_connected = QB_FALSE;
}
res = qb_ipc_us_ready(ow, 0, POLLIN);
_check_connection_state(c, res);
qb_ipcc_us_sock_close(ow->u.us.sock);
}
qb_ipcc_us_sock_close(c->setup.u.us.sock);
if (c->funcs.disconnect) {
c->funcs.disconnect(c);
}
@ -381,3 +394,20 @@ void *qb_ipcc_context_get(struct qb_ipcc_connection *c)
}
return c->context;
}
int32_t
qb_ipcc_is_connected(qb_ipcc_connection_t *c)
{
struct qb_ipc_one_way *ow;
if (c == NULL) {
return QB_FALSE;
}
ow = _response_sock_one_way_get(c);
if (ow) {
_check_connection_state(c, qb_ipc_us_ready(ow, 0, POLLIN));
}
return c->is_connected;
}

View File

@ -28,6 +28,8 @@
static void qb_ipcs_flowcontrol_set(struct qb_ipcs_connection *c,
int32_t fc_enable);
static int32_t
new_event_notification(struct qb_ipcs_connection * c);
static QB_LIST_DECLARE(qb_ipc_services);
@ -42,9 +44,17 @@ qb_ipcs_create(const char *name,
if (s == NULL) {
return NULL;
}
if (type == QB_IPC_NATIVE) {
#ifdef DISABLE_IPC_SHM
s->type = QB_IPC_SOCKET;
#else
s->type = QB_IPC_SHM;
#endif /* DISABLE_IPC_SHM */
} else {
s->type = type;
}
s->pid = getpid();
s->type = type;
s->needs_sock_for_poll = QB_FALSE;
s->poll_priority = QB_LOOP_MED;
s->ref_count = 1;
@ -91,21 +101,15 @@ qb_ipcs_run(struct qb_ipcs_service *s)
qb_ipcs_us_init((struct qb_ipcs_service *)s);
break;
case QB_IPC_SHM:
#ifdef DISABLE_IPC_SHM
res = -ENOTSUP;
#else
qb_ipcs_shm_init((struct qb_ipcs_service *)s);
#endif /* DISABLE_IPC_SHM */
break;
case QB_IPC_POSIX_MQ:
#ifdef HAVE_POSIX_MQ
qb_ipcs_pmq_init((struct qb_ipcs_service *)s);
#else
res = -ENOTSUP;
#endif /* HAVE_POSIX_MQ */
break;
case QB_IPC_SYSV_MQ:
#ifdef HAVE_SYSV_MQ
qb_ipcs_smq_init((struct qb_ipcs_service *)s);
#else
res = -ENOTSUP;
#endif /* HAVE_SYSV_MQ */
break;
default:
res = -EINVAL;
@ -130,15 +134,7 @@ _modify_dispatch_descriptor_(struct qb_ipcs_connection *c)
{
qb_ipcs_dispatch_mod_fn disp_mod = c->service->poll_fns.dispatch_mod;
if (c->service->type == QB_IPC_POSIX_MQ
&& !c->service->needs_sock_for_poll) {
#ifdef HAVE_MQUEUE_H
return disp_mod(c->service->poll_priority,
(int32_t) c->request.u.pmq.q,
c->poll_events, c,
qb_ipcs_dispatch_service_request);
#endif /* HAVE_MQUEUE_H */
} else if (c->service->type == QB_IPC_SOCKET) {
if (c->service->type == QB_IPC_SOCKET) {
return disp_mod(c->service->poll_priority,
c->event.u.us.sock,
c->poll_events, c,
@ -236,6 +232,29 @@ qb_ipcs_destroy(struct qb_ipcs_service *s)
/*
* connection API
*/
static struct qb_ipc_one_way *
_event_sock_one_way_get(struct qb_ipcs_connection * c)
{
if (c->service->needs_sock_for_poll) {
return &c->setup;
}
if (c->event.type == QB_IPC_SOCKET) {
return &c->event;
}
return NULL;
}
static struct qb_ipc_one_way *
_response_sock_one_way_get(struct qb_ipcs_connection * c)
{
if (c->service->needs_sock_for_poll) {
return &c->setup;
}
if (c->response.type == QB_IPC_SOCKET) {
return &c->response;
}
return NULL;
}
ssize_t
qb_ipcs_response_send(struct qb_ipcs_connection *c, const void *data,
@ -251,6 +270,13 @@ qb_ipcs_response_send(struct qb_ipcs_connection *c, const void *data,
if (res == size) {
c->stats.responses++;
} else if (res == -EAGAIN || res == -ETIMEDOUT) {
struct qb_ipc_one_way *ow = _response_sock_one_way_get(c);
if (ow) {
ssize_t res2 = qb_ipc_us_ready(ow, 0, POLLOUT);
if (res2 < 0) {
res = res2;
}
}
c->stats.send_retries++;
}
qb_ipcs_connection_unref(c);
@ -272,6 +298,13 @@ qb_ipcs_response_sendv(struct qb_ipcs_connection * c, const struct iovec * iov,
if (res > 0) {
c->stats.responses++;
} else if (res == -EAGAIN || res == -ETIMEDOUT) {
struct qb_ipc_one_way *ow = _response_sock_one_way_get(c);
if (ow) {
ssize_t res2 = qb_ipc_us_ready(ow, 0, POLLOUT);
if (res2 < 0) {
res = res2;
}
}
c->stats.send_retries++;
}
qb_ipcs_connection_unref(c);
@ -285,7 +318,7 @@ resend_event_notifications(struct qb_ipcs_connection *c)
ssize_t res = 0;
if (c->outstanding_notifiers > 0) {
res = qb_ipc_us_send(&c->setup, &c->outstanding_notifiers,
res = qb_ipc_us_send(&c->setup, c->receive_buf,
c->outstanding_notifiers);
}
if (res > 0) {
@ -313,15 +346,14 @@ new_event_notification(struct qb_ipcs_connection * c)
c->outstanding_notifiers++;
} else {
res = qb_ipc_us_send(&c->setup, &c->outstanding_notifiers, 1);
if (res == 1) {
return res;
if (res == -EAGAIN) {
/*
* notify the client later, when we can.
*/
c->outstanding_notifiers++;
c->poll_events = POLLOUT | POLLIN | POLLPRI | POLLNVAL;
(void)_modify_dispatch_descriptor_(c);
}
/*
* notify the client later, when we can.
*/
c->outstanding_notifiers++;
c->poll_events = POLLOUT | POLLIN | POLLPRI | POLLNVAL;
(void)_modify_dispatch_descriptor_(c);
}
return res;
}
@ -343,8 +375,20 @@ qb_ipcs_event_send(struct qb_ipcs_connection * c, const void *data, size_t size)
resn = new_event_notification(c);
if (resn < 0 && resn != -EAGAIN) {
errno = -resn;
qb_util_perror(LOG_WARNING, "new_event_notification");
qb_util_perror(LOG_WARNING,
"new_event_notification (%s)",
c->description);
res = resn;
}
} else if (res == -EAGAIN || res == -ETIMEDOUT) {
struct qb_ipc_one_way *ow = _event_sock_one_way_get(c);
if (ow) {
resn = qb_ipc_us_ready(ow, 0, POLLOUT);
if (resn < 0) {
res = resn;
}
}
c->stats.send_retries++;
}
qb_ipcs_connection_unref(c);
@ -369,8 +413,20 @@ qb_ipcs_event_sendv(struct qb_ipcs_connection * c,
resn = new_event_notification(c);
if (resn < 0 && resn != -EAGAIN) {
errno = -resn;
qb_util_perror(LOG_WARNING, "new_event_notification");
qb_util_perror(LOG_WARNING,
"new_event_notification (%s)",
c->description);
res = resn;
}
} else if (res == -EAGAIN || res == -ETIMEDOUT) {
struct qb_ipc_one_way *ow = _event_sock_one_way_get(c);
if (ow) {
resn = qb_ipc_us_ready(ow, 0, POLLOUT);
if (resn < 0) {
res = resn;
}
}
c->stats.send_retries++;
}
qb_ipcs_connection_unref(c);
@ -447,6 +503,7 @@ qb_ipcs_connection_alloc(struct qb_ipcs_service *s)
c->request.type = s->type;
c->response.type = s->type;
c->event.type = s->type;
(void)strlcpy(c->description, "not set yet", CONNECTION_DESCRIPTION);
return c;
}
@ -468,9 +525,9 @@ qb_ipcs_connection_unref(struct qb_ipcs_connection *c)
return;
}
if (c->refcount < 1) {
qb_util_log(LOG_ERR, "ref:%d state:%d fd:%d",
qb_util_log(LOG_ERR, "ref:%d state:%d (%s)",
c->refcount, c->state,
c->setup.u.us.sock);
c->description);
assert(0);
}
free_it = qb_atomic_int_dec_and_test(&c->refcount);
@ -494,17 +551,14 @@ qb_ipcs_disconnect(struct qb_ipcs_connection *c)
if (c == NULL) {
return;
}
qb_util_log(LOG_DEBUG, "%s() state:%d", __func__, c->state);
qb_util_log(LOG_DEBUG, "%s(%s) state:%d",
__func__, c->description, c->state);
if (c->state == QB_IPCS_CONNECTION_ACTIVE) {
c->state = QB_IPCS_CONNECTION_INACTIVE;
c->service->stats.closed_connections++;
if (c->service->needs_sock_for_poll && c->setup.u.us.sock > 0) {
(void)c->service->poll_fns.dispatch_del(c->setup.u.us.sock);
qb_ipcc_us_sock_close(c->setup.u.us.sock);
c->setup.u.us.sock = -1;
qb_ipcs_connection_unref(c);
}
qb_ipcs_sockets_disconnect(c);
/* return early as it's an incomplete connection.
*/
return;
@ -514,12 +568,7 @@ qb_ipcs_disconnect(struct qb_ipcs_connection *c)
c->service->stats.active_connections--;
c->service->stats.closed_connections++;
if (c->service->needs_sock_for_poll && c->setup.u.us.sock > 0) {
(void)c->service->poll_fns.dispatch_del(c->setup.u.us.sock);
qb_ipcc_us_sock_close(c->setup.u.us.sock);
c->setup.u.us.sock = -1;
qb_ipcs_connection_unref(c);
}
qb_ipcs_sockets_disconnect(c);
}
if (c->state == QB_IPCS_CONNECTION_SHUTTING_DOWN) {
res = 0;
@ -580,20 +629,21 @@ _process_request_(struct qb_ipcs_connection *c, int32_t ms_timeout)
if (size < 0) {
if (size != -EAGAIN && size != -ETIMEDOUT) {
qb_util_perror(LOG_ERR,
"recv from client connection failed");
"recv from client connection failed (%s)",
c->description);
} else {
c->stats.recv_retries++;
}
res = size;
goto cleanup;
}
c->stats.requests++;
if (hdr->id == QB_IPC_MSG_DISCONNECT) {
qb_util_log(LOG_DEBUG, "client requesting a disconnect");
} else if (size == 0 || hdr->id == QB_IPC_MSG_DISCONNECT) {
qb_util_log(LOG_DEBUG, "client requesting a disconnect (%s)",
c->description);
qb_ipcs_disconnect(c);
c = NULL;
res = -ESHUTDOWN;
} else {
c->stats.requests++;
res = c->service->serv_fns.msg_process(c, hdr, hdr->size);
/* 0 == good, negative == backoff */
if (res < 0) {
@ -603,7 +653,7 @@ _process_request_(struct qb_ipcs_connection *c, int32_t ms_timeout)
}
}
if (c->service->funcs.peek && c->service->funcs.reclaim) {
if (c && c->service->funcs.peek && c->service->funcs.reclaim) {
c->service->funcs.reclaim(&c->request);
}
@ -658,8 +708,12 @@ qb_ipcs_dispatch_connection_request(int32_t fd, int32_t revents, void *data)
int32_t recvd = 0;
ssize_t avail;
if (revents & POLLNVAL) {
qb_util_log(LOG_DEBUG, "NVAL conn (%s)", c->description);
return -EINVAL;
}
if (revents & POLLHUP) {
qb_util_log(LOG_DEBUG, "HUP conn:%p fd:%d", c, fd);
qb_util_log(LOG_DEBUG, "HUP conn (%s)", c->description);
qb_ipcs_disconnect(c);
return -ESHUTDOWN;
}
@ -668,7 +722,9 @@ qb_ipcs_dispatch_connection_request(int32_t fd, int32_t revents, void *data)
res = resend_event_notifications(c);
if (res < 0 && res != -EAGAIN) {
errno = -res;
qb_util_perror(LOG_WARNING, "resend_event_notifications");
qb_util_perror(LOG_WARNING,
"resend_event_notifications (%s)",
c->description);
}
if ((revents & POLLIN) == 0) {
return 0;
@ -681,10 +737,18 @@ qb_ipcs_dispatch_connection_request(int32_t fd, int32_t revents, void *data)
if (c->service->needs_sock_for_poll && avail == 0) {
res2 = qb_ipc_us_recv(&c->setup, bytes, 1, 0);
qb_util_log(LOG_WARNING,
"conn:%p Nothing in q but got POLLIN on fd:%d (res2:%d)",
c, fd, res2);
return 0;
if (qb_ipc_us_sock_error_is_disconnected(res2)) {
errno = -res2;
qb_util_perror(LOG_WARNING, "conn (%s) disconnected",
c->description);
qb_ipcs_disconnect(c);
return -ESHUTDOWN;
} else {
qb_util_log(LOG_WARNING,
"conn (%s) Nothing in q but got POLLIN on fd:%d (res2:%d)",
c->description, fd, res2);
return 0;
}
}
do {
@ -701,7 +765,9 @@ qb_ipcs_dispatch_connection_request(int32_t fd, int32_t revents, void *data)
res2 = qb_ipc_us_recv(&c->setup, bytes, recvd, -1);
if (res2 < 0) {
errno = -res2;
qb_util_perror(LOG_ERR, "error receiving from setup sock");
qb_util_perror(LOG_ERR,
"error receiving from setup sock (%s)",
c->description);
}
}
@ -711,7 +777,8 @@ qb_ipcs_dispatch_connection_request(int32_t fd, int32_t revents, void *data)
}
if (res != 0) {
errno = -res;
qb_util_perror(LOG_ERR, "request returned error");
qb_util_perror(LOG_ERR, "request returned error (%s)",
c->description);
qb_ipcs_connection_unref(c);
}
@ -746,12 +813,41 @@ qb_ipcs_connection_stats_get(qb_ipcs_connection_t * c,
}
memcpy(stats, &c->stats, sizeof(struct qb_ipcs_connection_stats));
if (clear_after_read) {
memset(&c->stats, 0, sizeof(struct qb_ipcs_connection_stats));
memset(&c->stats, 0, sizeof(struct qb_ipcs_connection_stats_2));
c->stats.client_pid = c->pid;
}
return 0;
}
struct qb_ipcs_connection_stats_2*
qb_ipcs_connection_stats_get_2(qb_ipcs_connection_t *c,
int32_t clear_after_read)
{
struct qb_ipcs_connection_stats_2* stats;
if (c == NULL) {
errno = EINVAL;
return NULL;
}
stats = calloc(1, sizeof(struct qb_ipcs_connection_stats_2));
if (stats == NULL) {
return NULL;
}
memcpy(stats, &c->stats, sizeof(struct qb_ipcs_connection_stats_2));
if (c->service->funcs.q_len_get) {
stats->event_q_length = c->service->funcs.q_len_get(&c->event);
} else {
stats->event_q_length = 0;
}
if (clear_after_read) {
memset(&c->stats, 0, sizeof(struct qb_ipcs_connection_stats_2));
c->stats.client_pid = c->pid;
}
return stats;
}
int32_t
qb_ipcs_stats_get(struct qb_ipcs_service * s,
struct qb_ipcs_stats * stats, int32_t clear_after_read)
@ -765,3 +861,14 @@ qb_ipcs_stats_get(struct qb_ipcs_service * s,
}
return 0;
}
void
qb_ipcs_connection_auth_set(qb_ipcs_connection_t *c, uid_t uid,
gid_t gid, mode_t mode)
{
if (c) {
c->auth.uid = uid;
c->auth.gid = gid;
c->auth.mode = mode;
}
}

View File

@ -7,5 +7,5 @@ Name: libqb
Version: @PACKAGE_VERSION@
Description: libqb
Requires:
Libs: -L${libdir} -lqb @LIB_RT@ -ldl
Libs: -L${libdir} -lqb @LIBS@
Cflags: -I${includedir}

View File

@ -225,7 +225,7 @@ qb_log_thread_log_write(struct qb_log_callsite *cs,
if (t->state != QB_LOG_STATE_ENABLED) {
continue;
}
if (t->threaded) {
if (!t->threaded) {
continue;
}
if (qb_bit_is_set(cs->targets, t->pos)) {
@ -287,6 +287,11 @@ qb_log_callsite_get(const char *function,
_custom_filter_fn(cs);
}
pthread_rwlock_unlock(&_listlock);
} else if (cs->tags != tags) {
cs->tags = tags;
if (_custom_filter_fn) {
_custom_filter_fn(cs);
}
}
return cs;
}
@ -730,6 +735,7 @@ qb_log_init(const char *name, int32_t facility, uint8_t priority)
for (i = 0; i < QB_LOG_TARGET_MAX; i++) {
conf[i].pos = i;
conf[i].debug = QB_FALSE;
conf[i].file_sync = QB_FALSE;
conf[i].state = QB_LOG_STATE_UNUSED;
(void)strlcpy(conf[i].name, name, PATH_MAX);
conf[i].facility = facility;
@ -894,7 +900,9 @@ qb_log_custom_close(int32_t t)
target = qb_log_target_get(t);
if (target->close) {
in_logger = QB_TRUE;
target->close(t);
in_logger = QB_FALSE;
}
qb_log_target_free(target);
}
@ -965,6 +973,9 @@ qb_log_ctl(int32_t t, enum qb_log_conf c, int32_t arg)
need_reload = QB_TRUE;
}
break;
case QB_LOG_CONF_FILE_SYNC:
conf[t].file_sync = arg;
break;
case QB_LOG_CONF_PRIORITY_BUMP:
conf[t].priority_bump = arg;
break;
@ -987,7 +998,9 @@ qb_log_ctl(int32_t t, enum qb_log_conf c, int32_t arg)
rc = -EINVAL;
}
if (rc == 0 && need_reload && conf[t].reload) {
in_logger = QB_TRUE;
conf[t].reload(t);
in_logger = QB_FALSE;
}
return rc;
}

View File

@ -38,6 +38,8 @@ _blackbox_reload(int32_t target)
}
/* <u32> file lineno
* <u32> tags
* <u8> priority
* <u32> function name length
* <string> function name
* <u32> buffer length
@ -49,8 +51,10 @@ _blackbox_vlogger(int32_t target,
{
size_t max_size;
size_t actual_size;
size_t fn_size;
uint32_t fn_size;
char *chunk;
char *msg_len_pt;
uint32_t msg_len;
struct qb_log_target *t = qb_log_target_get(target);
if (t->instance == NULL) {
@ -59,7 +63,7 @@ _blackbox_vlogger(int32_t target,
fn_size = strlen(cs->function) + 1;
actual_size = 2 * sizeof(uint32_t) + fn_size + sizeof(time_t);
actual_size = 4 * sizeof(uint32_t) + sizeof(uint8_t) + fn_size + sizeof(time_t);
max_size = actual_size + QB_LOG_MAX_LEN;
chunk = qb_rb_chunk_alloc(t->instance, max_size);
@ -68,6 +72,14 @@ _blackbox_vlogger(int32_t target,
memcpy(chunk, &cs->lineno, sizeof(uint32_t));
chunk += sizeof(uint32_t);
/* tags */
memcpy(chunk, &cs->tags, sizeof(uint32_t));
chunk += sizeof(uint32_t);
/* log level/priority */
memcpy(chunk, &cs->priority, sizeof(uint8_t));
chunk += sizeof(uint8_t);
/* function name */
memcpy(chunk, &fn_size, sizeof(uint32_t));
chunk += sizeof(uint32_t);
@ -78,8 +90,26 @@ _blackbox_vlogger(int32_t target,
memcpy(chunk, &timestamp, sizeof(time_t));
chunk += sizeof(time_t);
/* log message length */
msg_len_pt = chunk;
chunk += sizeof(uint32_t);
/* log message */
actual_size += qb_vsprintf_serialize(chunk, cs->format, ap);
msg_len = qb_vsnprintf_serialize(chunk, QB_LOG_MAX_LEN, cs->format, ap);
if(msg_len >= QB_LOG_MAX_LEN) {
chunk = msg_len_pt + sizeof(uint32_t); /* Reset */
msg_len = qb_vsnprintf_serialize(chunk, QB_LOG_MAX_LEN,
"Log message too long to be stored in the blackbox. "\
"Maximum is QB_LOG_MAX_LEN" , ap);
actual_size += msg_len;
}
actual_size += msg_len;
/* now that we know the length, write it
*/
memcpy(msg_len_pt, &msg_len, sizeof(uint32_t));
(void)qb_rb_chunk_commit(t->instance, actual_size);
}
@ -142,7 +172,8 @@ qb_log_blackbox_print_from_file(const char *bb_filename)
{
qb_ringbuffer_t *instance;
ssize_t bytes_read;
char chunk[512];
int max_size = 2 * QB_LOG_MAX_LEN;
char *chunk;
int fd;
char time_buf[64];
@ -156,17 +187,21 @@ qb_log_blackbox_print_from_file(const char *bb_filename)
if (instance == NULL) {
return;
}
chunk = malloc(max_size);
do {
char *ptr;
uint32_t lineno;
uint32_t tags;
uint8_t priority;
uint32_t fn_size;
char *function;
uint32_t len;
time_t timestamp;
uint32_t msg_len;
char message[QB_LOG_MAX_LEN];
bytes_read = qb_rb_chunk_read(instance, chunk, 512, 0);
bytes_read = qb_rb_chunk_read(instance, chunk, max_size, 0);
ptr = chunk;
if (bytes_read > 0) {
struct tm *tm;
@ -174,6 +209,14 @@ qb_log_blackbox_print_from_file(const char *bb_filename)
memcpy(&lineno, ptr, sizeof(uint32_t));
ptr += sizeof(uint32_t);
/* tags */
memcpy(&tags, ptr, sizeof(uint32_t));
ptr += sizeof(uint32_t);
/* priority */
memcpy(&priority, ptr, sizeof(uint8_t));
ptr += sizeof(uint8_t);
/* function size & name */
memcpy(&fn_size, ptr, sizeof(uint32_t));
ptr += sizeof(uint32_t);
@ -182,7 +225,7 @@ qb_log_blackbox_print_from_file(const char *bb_filename)
ptr += fn_size;
/* timestamp size & content */
memcpy(&timestamp, ptr, sizeof(uint32_t));
memcpy(&timestamp, ptr, sizeof(time_t));
ptr += sizeof(time_t);
tm = localtime(&timestamp);
if (tm) {
@ -193,6 +236,10 @@ qb_log_blackbox_print_from_file(const char *bb_filename)
snprintf(time_buf, sizeof(time_buf), "%ld",
(long int)timestamp);
}
/* message length */
memcpy(&msg_len, ptr, sizeof(uint32_t));
ptr += sizeof(uint32_t);
/* message content */
len = qb_vsnprintf_deserialize(message, QB_LOG_MAX_LEN, ptr);
len--;
@ -200,8 +247,12 @@ qb_log_blackbox_print_from_file(const char *bb_filename)
message[len] = '\0';
len--;
}
printf("%s %s():%d %s\n",
time_buf, function, lineno, message);
message[msg_len] = '\0';
printf("%-7s %s %s(%u):%u: %s\n",
qb_log_priority2str(priority),
time_buf, function, lineno, tags, message);
}
} while (bytes_read > 0);
qb_rb_close(instance);
free(chunk);
}

View File

@ -113,7 +113,7 @@ qb_log_dcs_get(int32_t * newly_created,
int32_t rc;
struct qb_log_callsite *cs = NULL;
struct callsite_list *csl_head;
struct callsite_list *csl_last;
struct callsite_list *csl_last = NULL;
struct callsite_list *csl;
const char *safe_filename = filename;
const char *safe_function = function;
@ -196,6 +196,27 @@ qb_log_dcs_init(void)
void
qb_log_dcs_fini(void)
{
struct callsite_list *csl_head;
struct callsite_list *csl_next;
struct callsite_list *csl;
int32_t i;
int32_t rc;
int32_t cnt = qb_array_num_bins_get(lookup_arr);
cnt *= qb_array_elems_per_bin_get(lookup_arr);
for (i = 0; i < cnt; i++) {
rc = qb_array_index(lookup_arr, i, (void **)&csl_head);
if (rc != 0 || csl_head->next == NULL) {
continue;
}
for (csl = csl_head->next; csl; csl = csl_next) {
csl_next = csl->next;
free(csl);
}
}
qb_array_free(lookup_arr);
qb_array_free(callsite_arr);
(void)qb_thread_lock_destroy(arr_next_lock);

View File

@ -26,6 +26,7 @@ _file_logger(int32_t t,
struct qb_log_callsite *cs, time_t timestamp, const char *msg)
{
char output_buffer[QB_LOG_MAX_LEN];
struct qb_log_target *target = qb_log_target_get(t);
FILE *f = qb_log_target_user_data_get(t);
if (f == NULL) {
@ -36,7 +37,11 @@ _file_logger(int32_t t,
qb_log_target_format(t, cs, timestamp, msg, output_buffer);
fprintf(f, "%s\n", output_buffer);
fflush(f);
if (target->file_sync) {
fsync(fileno(f));
}
}
static void

View File

@ -51,10 +51,14 @@ static struct syslog_names prioritynames[] = {
struct syslog_names facilitynames[] = {
{"auth", LOG_AUTH},
#if defined(LOG_AUTHPRIV)
{"authpriv", LOG_AUTHPRIV},
#endif
{"cron", LOG_CRON},
{"daemon", LOG_DAEMON},
#if defined(LOG_FTP)
{"ftp", LOG_FTP},
#endif
{"kern", LOG_KERN},
{"lpr", LOG_LPR},
{"mail", LOG_MAIL},
@ -110,6 +114,15 @@ qb_log_facility2str(int32_t fnum)
return NULL;
}
const char *
qb_log_priority2str(uint8_t priority)
{
if (priority > LOG_TRACE) {
return prioritynames[LOG_TRACE].c_name;
}
return prioritynames[priority].c_name;
}
void
qb_log_tags_stringify_fn_set(qb_log_tags_stringify_fn fn)
{
@ -366,16 +379,16 @@ qb_log_target_format(int32_t target,
}
size_t
qb_vsprintf_serialize(char *serialize, const char *fmt, va_list ap)
qb_vsnprintf_serialize(char *serialize, size_t max_len,
const char *fmt, va_list ap)
{
char *format;
char *p;
uint32_t location = 0;
int type_long = 0;
int type_longlong = 0;
p = stpcpy(serialize, fmt);
location = p - serialize + 1;
int sformat_length = 0;
int sformat_precision = 0;
uint32_t location = strlcpy(serialize, fmt, max_len) + 1;
format = (char *)fmt;
for (;;) {
@ -394,7 +407,12 @@ reprocess:
case '+': /* a sign should be used, ignore */
case '\'': /* group in thousands, ignore */
case 'I': /* glibc-ism locale alternative, ignore */
format++;
goto reprocess;
case '.': /* precision, ignore */
format++;
sformat_precision = 1;
goto reprocess;
case '0': /* field width, ignore */
case '1': /* field width, ignore */
case '2': /* field width, ignore */
@ -405,11 +423,17 @@ reprocess:
case '7': /* field width, ignore */
case '8': /* field width, ignore */
case '9': /* field width, ignore */
if(sformat_precision) {
sformat_length *= 10;
sformat_length += (format[0] - '0');
}
format++;
goto reprocess;
case '*': /* variable field width, save */ {
int arg_int = va_arg(ap, int);
if (location + sizeof (int) > max_len) {
return max_len;
}
memcpy(&serialize[location], &arg_int, sizeof (int));
location += sizeof(int);
format++;
@ -433,6 +457,9 @@ reprocess:
if (type_long) {
long int arg_int;
if (location + sizeof (long int) > max_len) {
return max_len;
}
arg_int = va_arg(ap, long int);
memcpy(&serialize[location], &arg_int,
sizeof(long int));
@ -442,6 +469,9 @@ reprocess:
} else if (type_longlong) {
long long int arg_int;
if (location + sizeof (long long int) > max_len) {
return max_len;
}
arg_int = va_arg(ap, long long int);
memcpy(&serialize[location], &arg_int,
sizeof(long long int));
@ -451,6 +481,9 @@ reprocess:
} else {
int arg_int;
if (location + sizeof (int) > max_len) {
return max_len;
}
arg_int = va_arg(ap, int);
memcpy(&serialize[location], &arg_int,
sizeof(int));
@ -469,6 +502,9 @@ reprocess:
{
double arg_double;
if (location + sizeof (double) > max_len) {
return max_len;
}
arg_double = va_arg(ap, double);
memcpy (&serialize[location], &arg_double, sizeof (double));
location += sizeof(double);
@ -480,6 +516,9 @@ reprocess:
int arg_int;
unsigned char arg_char;
if (location + sizeof (unsigned int) > max_len) {
return max_len;
}
arg_int = va_arg(ap, unsigned int);
arg_char = (unsigned char)arg_int;
memcpy (&serialize[location], &arg_char, sizeof (unsigned char));
@ -490,20 +529,42 @@ reprocess:
{
char *arg_string;
arg_string = va_arg(ap, char *);
p = stpcpy(&serialize[location], arg_string);
location += p - &serialize[location] + 1;
if (arg_string == NULL) {
location += strlcpy(&serialize[location],
"(null)",
QB_MIN(strlen("(null)") + 1,
max_len - location));
} else if (sformat_length) {
location += strlcpy(&serialize[location],
arg_string,
QB_MIN(sformat_length + 1,
(max_len - location)));
} else {
location += strlcpy(&serialize[location],
arg_string,
QB_MIN(strlen(arg_string) + 1,
max_len - location));
}
location++;
break;
}
case 'p':
{
void *arg_pointer;
arg_pointer = va_arg(ap, void *);
memcpy (&serialize[location], &arg_pointer, sizeof (void *));
location += sizeof (arg_pointer);
ptrdiff_t arg_pointer = va_arg(ap, ptrdiff_t);
if (location + sizeof (ptrdiff_t) > max_len) {
return max_len;
}
memcpy(&serialize[location], &arg_pointer, sizeof(ptrdiff_t));
location += sizeof(ptrdiff_t);
break;
}
case '%':
if (location + 1 > max_len) {
return max_len;
}
serialize[location++] = '%';
sformat_length = 0;
sformat_precision = 0;
break;
}
@ -527,19 +588,18 @@ qb_vsnprintf_deserialize(char *string, size_t str_len, const char *buf)
int type_longlong = 0;
int len;
string[0] = '\0';
format = (char *)buf;
for (;;) {
type_long = 0;
type_longlong = 0;
p = strchrnul((const char *)format, '%');
if (*p == '\0') {
p = stpcpy(&string[location], format);
location += p - &string[location] + 1;
break;
return strlcat(string, format, str_len) + 1;
}
/* copy from current to the next % */
len = p - format;
strncpy(&string[location], format, len);
memcpy(&string[location], format, len);
location += len;
format = p;
@ -681,11 +741,14 @@ reprocess:
}
case 'p':
{
ptrdiff_t pt;
memcpy(&pt, &buf[data_pos],
sizeof(ptrdiff_t));
fmt[fmt_pos++] = *format;
fmt[fmt_pos++] = '\0';
location = snprintf(&string[location],
str_len - location,
fmt, &buf[data_pos]);
location += snprintf(&string[location],
str_len - location,
fmt, pt);
data_pos += sizeof(void*);
format++;
break;

View File

@ -35,6 +35,7 @@ struct qb_log_target {
struct qb_list_head filter_head;
int32_t facility;
int32_t priority_bump;
int32_t file_sync;
int32_t debug;
size_t size;
char *format;
@ -93,7 +94,8 @@ struct qb_log_callsite *qb_log_dcs_get(int32_t *newly_created,
uint32_t lineno,
uint32_t tags);
size_t qb_vsprintf_serialize(char *serialize, const char *fmt, va_list ap);
const char * qb_log_priority2str(uint8_t priority);
size_t qb_vsnprintf_serialize(char *serialize, size_t max_len, const char *fmt, va_list ap);
size_t qb_vsnprintf_deserialize(char *string, size_t str_len, const char *buf);
void qb_log_target_format_static(int32_t target, const char * format, char *output_buffer);

View File

@ -121,7 +121,7 @@ qb_log_thread_priority_set(int32_t policy, int32_t priority)
#ifdef SCHED_IDLE
|| policy == SCHED_IDLE
#endif
#ifndef QB_DARWIN
#if defined(SCHED_BATCH) && !defined(QB_DARWIN)
|| policy == SCHED_BATCH
#endif
) {
@ -152,6 +152,8 @@ qb_log_thread_start(void)
}
wthread_active = 1;
sem_init(&logt_thread_start, 0, 0);
sem_init(&logt_print_finished, 0, 0);
res = pthread_create(&logt_thread_id, NULL,
qb_logt_worker_thread, NULL);
if (res != 0) {
@ -179,6 +181,8 @@ cleanup_pthread:
wthread_should_exit = 1;
sem_post(&logt_print_finished);
pthread_join(logt_thread_id, NULL);
sem_destroy(&logt_print_finished);
sem_destroy(&logt_thread_start);
return res;
}
@ -270,4 +274,6 @@ qb_log_thread_stop(void)
pthread_join(logt_thread_id, NULL);
}
(void)qb_thread_lock_destroy(logt_wthread_lock);
sem_destroy(&logt_print_finished);
sem_destroy(&logt_thread_start);
}

View File

@ -23,27 +23,10 @@
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
#ifdef HAVE_SYS_EPOLL_H
#include <sys/epoll.h>
#ifndef epoll_create1
int epoll_create1(int flags);
#endif /* workaround a set of sparc and alpha broken headers */
#endif /* HAVE_SYS_EPOLL_H */
#ifdef HAVE_SYS_POLL_H
#include <sys/poll.h>
#endif /* HAVE_SYS_POLL_H */
#ifndef S_SPLINT_S
#endif /* S_SPLINT_S */
#include <signal.h>
#include <qb/qbdefs.h>
#include <qb/qblist.h>
#include <qb/qbarray.h>
#include <qb/qbloop.h>
#include <qb/qbutil.h>
#include "loop_int.h"
#include "util_int.h"
#include "loop_poll_int.h"
/*
* Define this to log slow (>10ms) jobs.
@ -53,77 +36,19 @@ int epoll_create1(int flags);
/* logs, std(in|out|err), pipe */
#define POLL_FDS_USED_MISC 50
struct qb_poll_entry;
typedef int32_t(*qb_poll_add_to_jobs_fn) (struct qb_loop * l,
struct qb_poll_entry * pe);
struct qb_poll_entry {
struct qb_loop_item item;
qb_loop_poll_dispatch_fn poll_dispatch_fn;
enum qb_loop_priority p;
uint32_t install_pos;
struct pollfd ufd;
qb_poll_add_to_jobs_fn add_to_jobs;
uint32_t runs;
enum qb_poll_entry_state state;
uint32_t check;
};
struct qb_poll_source {
struct qb_loop_source s;
#ifdef HAVE_EPOLL
int32_t epollfd;
#define USE_EPOLL 1
#else
struct pollfd *ufds;
#ifdef HAVE_KQUEUE
#define USE_KQUEUE 1
#else
#define USE_POLL 1
#endif /* HAVE_KQUEUE */
#endif /* HAVE_EPOLL */
int32_t poll_entry_count;
qb_array_t *poll_entries;
qb_loop_poll_low_fds_event_fn low_fds_event_fn;
int32_t not_enough_fds;
};
static int32_t _qb_signal_add_to_jobs_(struct qb_loop *l,
struct qb_poll_entry *pe);
#ifdef HAVE_EPOLL
static int32_t
_poll_to_epoll_event_(int32_t event)
{
int32_t out = 0;
if (event & POLLIN)
out |= EPOLLIN;
if (event & POLLOUT)
out |= EPOLLOUT;
if (event & POLLPRI)
out |= EPOLLPRI;
if (event & POLLERR)
out |= EPOLLERR;
if (event & POLLHUP)
out |= EPOLLHUP;
if (event & POLLNVAL)
out |= EPOLLERR;
return out;
}
static int32_t
_epoll_to_poll_event_(int32_t event)
{
int32_t out = 0;
if (event & EPOLLIN)
out |= POLLIN;
if (event & EPOLLOUT)
out |= POLLOUT;
if (event & EPOLLPRI)
out |= POLLPRI;
if (event & EPOLLERR)
out |= POLLERR;
if (event & EPOLLHUP)
out |= POLLHUP;
return out;
}
#endif /* HAVE_EPOLL */
static void
_poll_entry_check_generate_(struct qb_poll_entry *pe)
{
@ -138,28 +63,6 @@ _poll_entry_check_generate_(struct qb_poll_entry *pe)
}
}
#if defined(HAVE_EPOLL)
static int32_t
_poll_entry_from_handle_(struct qb_poll_source *s,
uint64_t handle_in, struct qb_poll_entry **pe_pt)
{
int32_t res = 0;
uint32_t check = ((uint32_t) (((uint64_t) handle_in) >> 32));
uint32_t handle = handle_in & 0xffffffff;
struct qb_poll_entry *pe;
res = qb_array_index(s->poll_entries, handle, (void **)&pe);
if (res != 0) {
return res;
}
if (pe->check != check) {
return -EINVAL;
}
*pe_pt = pe;
return 0;
}
#endif /* HAVE_EPOLL */
static void
_poll_entry_mark_deleted_(struct qb_poll_entry *pe)
{
@ -224,8 +127,8 @@ _poll_dispatch_and_take_back_(struct qb_loop_item *item,
#endif /* DEBUG_DISPATCH_TIME */
}
static void
_poll_fds_usage_check_(struct qb_poll_source *s)
void
qb_poll_fds_usage_check_(struct qb_poll_source *s)
{
struct rlimit lim;
static int32_t socks_limit = 0;
@ -279,107 +182,6 @@ _poll_fds_usage_check_(struct qb_poll_source *s)
}
}
#ifdef HAVE_EPOLL
#define MAX_EVENTS 12
static int32_t
_poll_and_add_to_jobs_(struct qb_loop_source *src, int32_t ms_timeout)
{
int32_t i;
int32_t res;
int32_t event_count;
int32_t new_jobs = 0;
struct qb_poll_entry *pe = NULL;
struct qb_poll_source *s = (struct qb_poll_source *)src;
struct epoll_event events[MAX_EVENTS];
_poll_fds_usage_check_(s);
retry_poll:
event_count = epoll_wait(s->epollfd, events, MAX_EVENTS, ms_timeout);
if (errno == EINTR && event_count == -1) {
goto retry_poll;
} else if (event_count == -1) {
return -errno;
}
for (i = 0; i < event_count; i++) {
res = _poll_entry_from_handle_(s, events[i].data.u64, &pe);
if (res != 0) {
qb_util_log(LOG_WARNING,
"can't find poll entry for new event.");
continue;
}
if (pe->ufd.fd == -1 || pe->state == QB_POLL_ENTRY_DELETED) {
qb_util_log(LOG_WARNING,
"can't post new event to a deleted entry.");
/*
* empty/deleted
*/
continue;
}
if (events[i].events == pe->ufd.revents ||
pe->state == QB_POLL_ENTRY_JOBLIST) {
/*
* entry already in the job queue.
*/
continue;
}
pe->ufd.revents = _epoll_to_poll_event_(events[i].events);
new_jobs += pe->add_to_jobs(src->l, pe);
}
return new_jobs;
}
#else
static int32_t
_poll_and_add_to_jobs_(struct qb_loop_source *src, int32_t ms_timeout)
{
int32_t i;
int32_t res;
int32_t new_jobs = 0;
struct qb_poll_entry *pe;
struct qb_poll_source *s = (struct qb_poll_source *)src;
_poll_fds_usage_check_(s);
for (i = 0; i < s->poll_entry_count; i++) {
assert(qb_array_index(s->poll_entries, i, (void **)&pe) == 0);
memcpy(&s->ufds[i], &pe->ufd, sizeof(struct pollfd));
}
retry_poll:
res = poll(s->ufds, s->poll_entry_count, ms_timeout);
if (errno == EINTR && res == -1) {
goto retry_poll;
} else if (res == -1) {
return -errno;
}
for (i = 0; i < s->poll_entry_count; i++) {
if (s->ufds[i].fd == -1 || s->ufds[i].revents == 0) {
/*
* empty entry
*/
continue;
}
assert(qb_array_index(s->poll_entries, i, (void **)&pe) == 0);
if (pe->state != QB_POLL_ENTRY_ACTIVE ||
s->ufds[i].revents == pe->ufd.revents) {
/*
* Wrong state to accept an event.
*/
continue;
}
pe->ufd.revents = s->ufds[i].revents;
new_jobs += pe->add_to_jobs(src->l, pe);
}
return new_jobs;
}
#endif /* HAVE_EPOLL */
struct qb_loop_source *
qb_loop_poll_create(struct qb_loop *l)
@ -390,18 +192,21 @@ qb_loop_poll_create(struct qb_loop *l)
}
s->s.l = l;
s->s.dispatch_and_take_back = _poll_dispatch_and_take_back_;
s->s.poll = _poll_and_add_to_jobs_;
s->poll_entries = qb_array_create_2(16, sizeof(struct qb_poll_entry), 16);
s->poll_entry_count = 0;
s->low_fds_event_fn = NULL;
s->not_enough_fds = 0;
#ifdef HAVE_EPOLL
s->epollfd = epoll_create1(EPOLL_CLOEXEC);
#else
s->ufds = 0;
#endif /* HAVE_EPOLL */
#ifdef USE_EPOLL
(void)qb_epoll_init(s);
#endif
#ifdef USE_KQUEUE
(void)qb_kqueue_init(s);
#endif
#ifdef USE_POLL
(void)qb_poll_init(s);
#endif /* USE_POLL */
return (struct qb_loop_source *)s;
}
@ -411,12 +216,9 @@ qb_loop_poll_destroy(struct qb_loop *l)
{
struct qb_poll_source *s = (struct qb_poll_source *)l->fd_source;
qb_array_free(s->poll_entries);
#ifdef HAVE_EPOLL
if (s->epollfd != -1) {
close(s->epollfd);
s->epollfd = -1;
}
#endif /* HAVE_EPOLL */
s->driver.fini(s);
free(s);
}
@ -437,10 +239,6 @@ _get_empty_array_position_(struct qb_poll_source *s)
uint32_t install_pos;
int32_t res = 0;
struct qb_poll_entry *pe;
#ifndef HAVE_EPOLL
struct pollfd *ufds;
int32_t new_size = 0;
#endif /* HAVE_EPOLL */
for (found = 0, install_pos = 0;
install_pos < s->poll_entry_count; install_pos++) {
@ -453,6 +251,15 @@ _get_empty_array_position_(struct qb_poll_source *s)
}
if (found == 0) {
#ifdef USE_POLL
struct pollfd *ufds;
int32_t new_size = (s->poll_entry_count + 1) * sizeof(struct pollfd);
ufds = realloc(s->ufds, new_size);
if (ufds == NULL) {
return -ENOMEM;
}
s->ufds = ufds;
#endif /* USE_POLL */
/*
* Grow pollfd list
*/
@ -460,14 +267,6 @@ _get_empty_array_position_(struct qb_poll_source *s)
if (res != 0) {
return res;
}
#ifndef HAVE_EPOLL
new_size = (s->poll_entry_count + 1) * sizeof(struct pollfd);
ufds = realloc(s->ufds, new_size);
if (ufds == NULL) {
return -ENOMEM;
}
s->ufds = ufds;
#endif /* HAVE_EPOLL */
s->poll_entry_count += 1;
install_pos = s->poll_entry_count - 1;
@ -484,9 +283,6 @@ _poll_add_(struct qb_loop *l,
uint32_t install_pos;
int32_t res = 0;
struct qb_poll_source *s;
#ifdef HAVE_EPOLL
struct epoll_event ev;
#endif /* HAVE_EPOLL */
if (l == NULL) {
return -EINVAL;
@ -507,17 +303,14 @@ _poll_add_(struct qb_loop *l,
pe->item.source = (struct qb_loop_source *)l->fd_source;
pe->p = p;
pe->runs = 0;
#ifdef HAVE_EPOLL
ev.events = _poll_to_epoll_event_(events);
ev.data.u64 = (((uint64_t) (pe->check)) << 32) | pe->install_pos;
if (epoll_ctl(s->epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
res = -errno;
qb_util_perror(LOG_ERR, "epoll_ctl(add)");
res = s->driver.add(s, pe, fd, events);
if (res == 0) {
*pe_pt = pe;
return 0;
} else {
pe->state = QB_POLL_ENTRY_EMPTY;
return res;
}
#endif /* HAVE_EPOLL */
*pe_pt = pe;
return (res);
}
static int32_t
@ -548,6 +341,11 @@ qb_loop_poll_add(struct qb_loop * lp,
size = ((struct qb_poll_source *)l->fd_source)->poll_entry_count;
res = _poll_add_(l, p, fd, events, data, &pe);
if (res != 0) {
qb_util_perror(LOG_ERR,
"couldn't add poll entryfor FD %d", fd);
return res;
}
new_size = ((struct qb_poll_source *)l->fd_source)->poll_entry_count;
pe->poll_dispatch_fn = dispatch_fn;
@ -573,9 +371,6 @@ qb_loop_poll_mod(struct qb_loop * lp,
int32_t res = 0;
struct qb_poll_entry *pe;
struct qb_poll_source *s;
#ifdef HAVE_EPOLL
struct epoll_event ev;
#endif /* HAVE_EPOLL */
struct qb_loop *l = lp;
if (l == NULL) {
@ -600,14 +395,7 @@ qb_loop_poll_mod(struct qb_loop * lp,
pe->item.user_data = data;
pe->p = p;
if (pe->ufd.events != events) {
#ifdef HAVE_EPOLL
ev.events = _poll_to_epoll_event_(events);
ev.data.u64 = (((uint64_t) (pe->check)) << 32) | i;
if (epoll_ctl(s->epollfd, EPOLL_CTL_MOD, fd, &ev) == -1) {
res = -errno;
qb_util_perror(LOG_ERR, "epoll_ctl(mod)");
}
#endif /* HAVE_EPOLL */
res = s->driver.mod(s, pe, fd, events);
pe->ufd.events = events;
}
return res;
@ -641,16 +429,7 @@ qb_loop_poll_del(struct qb_loop * lp, int32_t fd)
if (pe->state == QB_POLL_ENTRY_JOBLIST) {
qb_loop_level_item_del(&l->level[pe->p], &pe->item);
}
#ifdef HAVE_EPOLL
if (epoll_ctl(s->epollfd, EPOLL_CTL_DEL, fd, NULL) == -1) {
res = -errno;
qb_util_perror(LOG_WARNING, "epoll_ctl(del)");
}
#else
s->ufds[i].fd = -1;
s->ufds[i].events = 0;
s->ufds[i].revents = 0;
#endif /* HAVE_EPOLL */
res = s->driver.del(s, pe, fd, i);
_poll_entry_mark_deleted_(pe);
return res;
}

209
lib/loop_poll_epoll.c Normal file
View File

@ -0,0 +1,209 @@
/*
* Copyright (C) 2012 Red Hat, Inc.
*
* Author: Angus Salkeld <asalkeld@redhat.com>
*
* This file is part of libqb.
*
* libqb 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.
*
* libqb 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 libqb. If not, see <http://www.gnu.org/licenses/>.
*/
#include "os_base.h"
#include "loop_poll_int.h"
#ifdef HAVE_SYS_EPOLL_H
#include <sys/epoll.h>
#ifndef epoll_create1
int epoll_create1(int flags);
#endif /* workaround a set of sparc and alpha broken headers */
#endif /* HAVE_SYS_EPOLL_H */
#define MAX_EVENTS 12
static int32_t
_poll_to_epoll_event_(int32_t event)
{
int32_t out = 0;
if (event & POLLIN)
out |= EPOLLIN;
if (event & POLLOUT)
out |= EPOLLOUT;
if (event & POLLPRI)
out |= EPOLLPRI;
if (event & POLLERR)
out |= EPOLLERR;
if (event & POLLHUP)
out |= EPOLLHUP;
if (event & POLLNVAL)
out |= EPOLLERR;
return out;
}
static int32_t
_epoll_to_poll_event_(int32_t event)
{
int32_t out = 0;
if (event & EPOLLIN)
out |= POLLIN;
if (event & EPOLLOUT)
out |= POLLOUT;
if (event & EPOLLPRI)
out |= POLLPRI;
if (event & EPOLLERR)
out |= POLLERR;
if (event & EPOLLHUP)
out |= POLLHUP;
return out;
}
static void
_fini(struct qb_poll_source *s)
{
if (s->epollfd != -1) {
close(s->epollfd);
s->epollfd = -1;
}
}
static int32_t
_add(struct qb_poll_source *s, struct qb_poll_entry *pe, int32_t fd, int32_t events)
{
struct epoll_event ev;
int32_t res = 0;
ev.events = _poll_to_epoll_event_(events);
ev.data.u64 = (((uint64_t) (pe->check)) << 32) | pe->install_pos;
if (epoll_ctl(s->epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
res = -errno;
qb_util_perror(LOG_ERR, "epoll_ctl(add)");
}
return res;
}
static int32_t
_mod(struct qb_poll_source *s, struct qb_poll_entry *pe, int32_t fd, int32_t events)
{
struct epoll_event ev;
int32_t res = 0;
ev.events = _poll_to_epoll_event_(events);
ev.data.u64 = (((uint64_t) (pe->check)) << 32) | pe->install_pos;
if (epoll_ctl(s->epollfd, EPOLL_CTL_MOD, fd, &ev) == -1) {
res = -errno;
qb_util_perror(LOG_DEBUG, "epoll_ctl(mod)");
}
return res;
}
static int32_t
_del(struct qb_poll_source *s, struct qb_poll_entry *pe, int32_t fd, int32_t arr_index)
{
int32_t res = 0;
if (epoll_ctl(s->epollfd, EPOLL_CTL_DEL, fd, NULL) == -1) {
res = -errno;
qb_util_perror(LOG_DEBUG, "epoll_ctl(del)");
}
return res;
}
static int32_t
_poll_entry_from_handle_(struct qb_poll_source *s,
uint64_t handle_in, struct qb_poll_entry **pe_pt)
{
int32_t res = 0;
uint32_t check = ((uint32_t) (((uint64_t) handle_in) >> 32));
uint32_t handle = handle_in & 0xffffffff;
struct qb_poll_entry *pe;
res = qb_array_index(s->poll_entries, handle, (void **)&pe);
if (res != 0) {
return res;
}
if (pe->check != check) {
return -EINVAL;
}
*pe_pt = pe;
return 0;
}
static int32_t
_poll_and_add_to_jobs_(struct qb_loop_source *src, int32_t ms_timeout)
{
int32_t i;
int32_t res;
int32_t event_count;
int32_t new_jobs = 0;
struct qb_poll_entry *pe = NULL;
struct qb_poll_source *s = (struct qb_poll_source *)src;
struct epoll_event events[MAX_EVENTS];
qb_poll_fds_usage_check_(s);
retry_poll:
event_count = epoll_wait(s->epollfd, events, MAX_EVENTS, ms_timeout);
if (errno == EINTR && event_count == -1) {
goto retry_poll;
} else if (event_count == -1) {
return -errno;
}
for (i = 0; i < event_count; i++) {
res = _poll_entry_from_handle_(s, events[i].data.u64, &pe);
if (res != 0) {
qb_util_log(LOG_WARNING,
"can't find poll entry for new event.");
continue;
}
if (pe->ufd.fd == -1 || pe->state == QB_POLL_ENTRY_DELETED) {
qb_util_log(LOG_WARNING,
"can't post new event to a deleted entry.");
/*
* empty/deleted
*/
continue;
}
if (events[i].events == pe->ufd.revents ||
pe->state == QB_POLL_ENTRY_JOBLIST) {
/*
* entry already in the job queue.
*/
continue;
}
pe->ufd.revents = _epoll_to_poll_event_(events[i].events);
new_jobs += pe->add_to_jobs(src->l, pe);
}
return new_jobs;
}
int32_t
qb_epoll_init(struct qb_poll_source *s)
{
s->epollfd = epoll_create1(EPOLL_CLOEXEC);
if (s->epollfd < 0) {
return -errno;
}
s->driver.fini = _fini;
s->driver.add = _add;
s->driver.mod = _mod;
s->driver.del = _del;
s->s.poll = _poll_and_add_to_jobs_;
return 0;
}

91
lib/loop_poll_int.h Normal file
View File

@ -0,0 +1,91 @@
/*
* Copyright (C) 2012 Red Hat, Inc.
*
* Author: Angus Salkeld <asalkeld@redhat.com>
*
* This file is part of libqb.
*
* libqb 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.
*
* libqb 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 libqb. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef QB_LOOP_POLL_INT_DEFINED
#define QB_LOOP_POLL_INT_DEFINED
#include "os_base.h"
#ifdef HAVE_SYS_POLL_H
#include <sys/poll.h>
#endif /* HAVE_SYS_POLL_H */
#include <qb/qbdefs.h>
#include <qb/qblist.h>
#include <qb/qbarray.h>
#include <qb/qbutil.h>
#include "loop_int.h"
#include "util_int.h"
struct qb_poll_entry;
typedef int32_t(*qb_poll_add_to_jobs_fn) (struct qb_loop * l,
struct qb_poll_entry * pe);
struct qb_poll_entry {
struct qb_loop_item item;
qb_loop_poll_dispatch_fn poll_dispatch_fn;
enum qb_loop_priority p;
uint32_t install_pos;
struct pollfd ufd;
qb_poll_add_to_jobs_fn add_to_jobs;
uint32_t runs;
enum qb_poll_entry_state state;
uint32_t check;
};
struct qb_poll_source;
struct qb_loop_driver {
int32_t (*poll)(struct qb_loop_source* s, int32_t ms_timeout);
void (*fini)(struct qb_poll_source *s);
int32_t (*add)(struct qb_poll_source *s, struct qb_poll_entry *pe, int32_t fd, int32_t events);
int32_t (*mod)(struct qb_poll_source *s, struct qb_poll_entry *pe, int32_t fd, int32_t events);
int32_t (*del)(struct qb_poll_source *s, struct qb_poll_entry *pe, int32_t fd, int32_t arr_index);
};
struct qb_poll_source {
struct qb_loop_source s;
int32_t poll_entry_count;
qb_array_t *poll_entries;
qb_loop_poll_low_fds_event_fn low_fds_event_fn;
int32_t not_enough_fds;
#if defined(HAVE_EPOLL) || defined(HAVE_KQUEUE)
int32_t epollfd;
#else
struct pollfd *ufds;
#endif /* HAVE_EPOLL */
struct qb_loop_driver driver;
};
void
qb_poll_fds_usage_check_(struct qb_poll_source *s);
int32_t
qb_epoll_init(struct qb_poll_source *s);
int32_t
qb_poll_init(struct qb_poll_source *s);
int32_t
qb_kqueue_init(struct qb_poll_source *s);
#endif /* QB_LOOP_POLL_INT_DEFINED */

210
lib/loop_poll_kqueue.c Normal file
View File

@ -0,0 +1,210 @@
/*
* Copyright (C) 2012 Red Hat, Inc.
*
* Author: Angus Salkeld <asalkeld@redhat.com>
*
* This file is part of libqb.
*
* libqb 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.
*
* libqb 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 libqb. If not, see <http://www.gnu.org/licenses/>.
*/
#include "os_base.h"
#include "loop_poll_int.h"
#ifdef HAVE_SYS_EVENT_H
#include <sys/event.h>
#endif /* HAVE_SYS_EVENT_H */
#define MAX_EVENTS 12
static int32_t
_poll_to_filter_(int32_t event)
{
int32_t out = 0;
if (event & POLLIN)
out |= EVFILT_READ;
if (event & POLLOUT)
out |= EVFILT_WRITE;
return out;
}
static void
_fini(struct qb_poll_source *s)
{
if (s->epollfd != -1) {
close(s->epollfd);
s->epollfd = -1;
}
}
static int32_t
_add(struct qb_poll_source *s, struct qb_poll_entry *pe, int32_t fd, int32_t events)
{
int32_t res = 0;
struct kevent ke;
short filters = _poll_to_filter_(events);
EV_SET(&ke, fd, filters, EV_ADD, 0, 0, (intptr_t)pe);
res = kevent(s->epollfd, &ke, 1, NULL, 0, NULL);
if (res == -1) {
res = -errno;
qb_util_perror(LOG_ERR, "kevent(add)");
}
return res;
}
static int32_t
_mod(struct qb_poll_source *s, struct qb_poll_entry *pe, int32_t fd, int32_t events)
{
int32_t res = 0;
struct kevent ke[2];
short new_filters = _poll_to_filter_(events);
short old_filters = _poll_to_filter_(pe->ufd.events);
EV_SET(&ke[0], fd, old_filters, EV_DELETE, 0, 0, (intptr_t)pe);
EV_SET(&ke[1], fd, new_filters, EV_ADD, 0, 0, (intptr_t)pe);
res = kevent(s->epollfd, ke, 2, NULL, 0, NULL);
if (res == -1) {
res = -errno;
qb_util_perror(LOG_ERR, "kevent(mod)");
}
return res;
}
static int32_t
_del(struct qb_poll_source *s, struct qb_poll_entry *pe, int32_t fd, int32_t events)
{
int32_t res = 0;
struct kevent ke;
short filters = _poll_to_filter_(events);
EV_SET(&ke, fd, filters, EV_DELETE, 0, 0, (intptr_t)pe);
res = kevent(s->epollfd, &ke, 1, NULL, 0, NULL);
if (res == -1 && errno == ENOENT) {
/*
* Not a problem already cleaned up.
*/
res = 0;
} else if (res == -1) {
res = -errno;
qb_util_perror(LOG_ERR, "kevent(del)");
}
return res;
}
static int32_t
_poll_and_add_to_jobs_(struct qb_loop_source *src, int32_t ms_timeout)
{
int32_t i;
int32_t event_count;
int32_t new_jobs = 0;
int32_t revents = 0;
struct qb_poll_entry *pe = NULL;
struct qb_poll_source *s = (struct qb_poll_source *)src;
struct kevent events[MAX_EVENTS];
struct timespec timeout = { 0, 0 };
struct timespec *timeout_pt = &timeout;
if (ms_timeout > 0) {
qb_timespec_add_ms(&timeout, ms_timeout);
} else if (ms_timeout < 0) {
timeout_pt = NULL;
}
qb_poll_fds_usage_check_(s);
retry_poll:
event_count = kevent(s->epollfd, NULL, 0, events, MAX_EVENTS, timeout_pt);
if (errno == EINTR && event_count == -1) {
goto retry_poll;
} else if (event_count == -1) {
qb_util_perror(LOG_ERR, "kevent(poll)");
return -errno;
}
for (i = 0; i < event_count; i++) {
revents = 0;
pe = (struct qb_poll_entry *)events[i].udata;
if (events[i].flags) {
qb_util_log(LOG_TRACE,
"got flags %d on fd %d.", events[i].flags,
pe->ufd.fd);
}
if (events[i].flags & EV_ERROR) {
qb_util_log(LOG_WARNING,
"got EV_ERROR on fd %d.", pe->ufd.fd);
revents |= POLLERR;
}
if (events[i].flags & EV_EOF) {
qb_util_log(LOG_INFO,
"got EV_EOF on fd %d.", pe->ufd.fd);
revents |= POLLHUP;
}
if (events[i].filter == EVFILT_READ) {
revents |= POLLIN;
}
if (events[i].filter == EVFILT_WRITE) {
revents |= POLLOUT;
}
if (pe->ufd.fd == -1 || pe->state == QB_POLL_ENTRY_DELETED) {
qb_util_log(LOG_WARNING,
"can't post new event to a deleted entry.");
/*
* empty/deleted
*/
EV_SET(&events[i], events[i].ident, events[i].filter,
EV_DELETE, 0, 0, (intptr_t)pe);
(void)kevent(s->epollfd, &events[i], 1, NULL, 0, NULL);
continue;
}
if (pe->ufd.fd != events[i].ident) {
qb_util_log(LOG_WARNING,
"can't find poll entry for new event.");
continue;
}
if (revents == pe->ufd.revents ||
pe->state == QB_POLL_ENTRY_JOBLIST) {
/*
* entry already in the job queue.
*/
continue;
}
pe->ufd.revents = revents;
new_jobs += pe->add_to_jobs(src->l, pe);
}
return new_jobs;
}
int32_t
qb_kqueue_init(struct qb_poll_source *s)
{
s->epollfd = kqueue();
if (s->epollfd < 0) {
qb_util_perror(LOG_ERR, "kqueue()");
return -errno;
}
s->driver.fini = _fini;
s->driver.add = _add;
s->driver.mod = _mod;
s->driver.del = _del;
s->s.poll = _poll_and_add_to_jobs_;
return 0;
}

109
lib/loop_poll_poll.c Normal file
View File

@ -0,0 +1,109 @@
/*
* Copyright (C) 2012 Red Hat, Inc.
*
* Author: Angus Salkeld <asalkeld@redhat.com>
*
* This file is part of libqb.
*
* libqb 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.
*
* libqb 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 libqb. If not, see <http://www.gnu.org/licenses/>.
*/
#include "os_base.h"
#include "loop_poll_int.h"
static void
_fini(struct qb_poll_source *s)
{
}
static int32_t
_add(struct qb_poll_source *s, struct qb_poll_entry *pe, int32_t fd, int32_t events)
{
return 0;
}
static int32_t
_mod(struct qb_poll_source *s, struct qb_poll_entry *pe, int32_t fd, int32_t events)
{
return 0;
}
static int32_t
_del(struct qb_poll_source *s, struct qb_poll_entry *pe, int32_t fd, int32_t i)
{
s->ufds[i].fd = -1;
s->ufds[i].events = 0;
s->ufds[i].revents = 0;
return 0;
}
static int32_t
_poll_and_add_to_jobs_(struct qb_loop_source *src, int32_t ms_timeout)
{
int32_t i;
int32_t res;
int32_t new_jobs = 0;
struct qb_poll_entry *pe;
struct qb_poll_source *s = (struct qb_poll_source *)src;
qb_poll_fds_usage_check_(s);
for (i = 0; i < s->poll_entry_count; i++) {
assert(qb_array_index(s->poll_entries, i, (void **)&pe) == 0);
memcpy(&s->ufds[i], &pe->ufd, sizeof(struct pollfd));
}
retry_poll:
res = poll(s->ufds, s->poll_entry_count, ms_timeout);
if (errno == EINTR && res == -1) {
goto retry_poll;
} else if (res == -1) {
return -errno;
}
for (i = 0; i < s->poll_entry_count; i++) {
if (s->ufds[i].fd == -1 || s->ufds[i].revents == 0) {
/*
* empty entry
*/
continue;
}
assert(qb_array_index(s->poll_entries, i, (void **)&pe) == 0);
if (pe->state != QB_POLL_ENTRY_ACTIVE ||
s->ufds[i].revents == pe->ufd.revents) {
/*
* Wrong state to accept an event.
*/
continue;
}
pe->ufd.revents = s->ufds[i].revents;
new_jobs += pe->add_to_jobs(src->l, pe);
}
return new_jobs;
}
int32_t
qb_poll_init(struct qb_poll_source *s)
{
s->ufds = 0;
s->driver.fini = _fini;
s->driver.add = _add;
s->driver.mod = _mod;
s->driver.del = _del;
s->s.poll = _poll_and_add_to_jobs_;
return 0;
}

View File

@ -34,6 +34,35 @@ do { \
#define DEBUG_PRINTF(format, args...)
#endif /* CRAZY_DEBUG_PRINTFS */
/*
* move the write pointer to the next 128 byte boundary
* write_pt goes in 4 bytes (sizeof(uint32_t))
* #define USE_CACHE_LINE_ALIGNMENT 1
*/
#ifdef USE_CACHE_LINE_ALIGNMENT
#define QB_CACHE_LINE_SIZE 128
#define QB_CACHE_LINE_WORDS (QB_CACHE_LINE_SIZE/sizeof(uint32_t))
#define idx_cache_line_step(idx) \
do { \
if (idx % QB_CACHE_LINE_WORDS) { \
idx += (QB_CACHE_LINE_WORDS - (idx % QB_CACHE_LINE_WORDS)); \
} \
if (idx > (rb->shared_hdr->word_size - 1)) { \
idx = ((idx) % (rb->shared_hdr->word_size)); \
} \
} while (0)
#else
#define QB_CACHE_LINE_SIZE 0
#define QB_CACHE_LINE_WORDS 0
#define idx_cache_line_step(idx) \
do { \
if (idx > (rb->shared_hdr->word_size - 1)) { \
idx = ((idx) % (rb->shared_hdr->word_size)); \
} \
} while (0)
#endif
/* the chunk header is two words
* 1) the chunk data size
* 2) the magic number
@ -46,16 +75,31 @@ do { \
* So:
* qb_rb_space_free() >= QB_RB_CHUNK_MARGIN + new data chunk
* The extra word size is to allow for non word sized data chunks.
* QB_CACHE_LINE_WORDS is to make sure we have space to align the
* chunk.
*/
#define QB_RB_CHUNK_MARGIN (sizeof(uint32_t) * (QB_RB_CHUNK_HEADER_WORDS + 1))
#define QB_RB_CHUNK_MAGIC 0xAAAAAAAA
#define QB_RB_WORD_ALIGN 1
#define QB_RB_CHUNK_MARGIN (sizeof(uint32_t) * (QB_RB_CHUNK_HEADER_WORDS +\
QB_RB_WORD_ALIGN +\
QB_CACHE_LINE_WORDS))
#define QB_RB_CHUNK_MAGIC 0xA1A1A1A1
#define QB_RB_CHUNK_MAGIC_DEAD 0xD0D0D0D0
#define QB_RB_CHUNK_MAGIC_ALLOC 0xA110CED0
#define QB_RB_CHUNK_SIZE_GET(rb, pointer) \
rb->shared_data[pointer]
#define QB_RB_CHUNK_MAGIC_GET(rb, pointer) \
rb->shared_data[(pointer + 1) % rb->shared_hdr->word_size]
#define QB_RB_CHUNK_MAGIC_SET(rb, pointer, new_val) \
rb->shared_data[(pointer + 1) % rb->shared_hdr->word_size] = new_val;
#define QB_RB_CHUNK_DATA_GET(rb, pointer) \
&rb->shared_data[(pointer + QB_RB_CHUNK_HEADER_WORDS) % rb->shared_hdr->word_size]
#define QB_RB_WRITE_PT_INDEX (rb->shared_hdr->word_size)
#define QB_RB_READ_PT_INDEX (rb->shared_hdr->word_size + 1)
#define QB_MAGIC_ASSERT(_ptr_) \
do { \
uint32_t chunk_magic = QB_RB_CHUNK_MAGIC_GET(rb, _ptr_); \
if (chunk_magic != QB_RB_CHUNK_MAGIC) print_header(rb); \
assert(chunk_magic == QB_RB_CHUNK_MAGIC); \
} while (0)
#define idx_step(idx) \
do { \
@ -64,33 +108,8 @@ do { \
} \
} while (0)
/*
* move the write pointer to the next 32 byte boundary
* write_pt goes in 4 bytes (sizeof(uint32_t))
*/
/*
* #define USE_CACHE_LINE_ALIGNMENT 1
*/
#ifdef USE_CACHE_LINE_ALIGNMENT
#define idx_cache_line_step(idx) \
do { \
if (idx % 8) { \
idx += (8 - (idx % 8)); \
} \
if (idx > (rb->shared_hdr->word_size - 1)) { \
idx = ((idx) % (rb->shared_hdr->word_size)); \
} \
} while (0)
#else
#define idx_cache_line_step(idx) \
do { \
if (idx > (rb->shared_hdr->word_size - 1)) { \
idx = ((idx) % (rb->shared_hdr->word_size)); \
} \
} while (0)
#endif
static void qb_rb_chunk_check(struct qb_ringbuffer_s * rb, uint32_t pointer);
static void print_header(struct qb_ringbuffer_s * rb);
static void _rb_chunk_reclaim(struct qb_ringbuffer_s * rb);
qb_ringbuffer_t *
qb_rb_open(const char *name, size_t size, uint32_t flags,
@ -221,7 +240,9 @@ cleanup_hdr:
}
if (rb && (flags & QB_RB_FLAG_CREATE)) {
unlink(rb->shared_hdr->hdr_path);
(void)rb->sem_destroy_fn(rb);
if (rb->sem_destroy_fn) {
(void)rb->sem_destroy_fn(rb);
}
}
if (rb && (rb->shared_hdr != MAP_FAILED && rb->shared_hdr != NULL)) {
munmap(rb->shared_hdr, sizeof(struct qb_ringbuffer_shared_s));
@ -240,7 +261,9 @@ qb_rb_close(struct qb_ringbuffer_s * rb)
(void)qb_atomic_int_dec_and_test(&rb->shared_hdr->ref_count);
if (rb->flags & QB_RB_FLAG_CREATE) {
(void)rb->sem_destroy_fn(rb);
if (rb->sem_destroy_fn) {
(void)rb->sem_destroy_fn(rb);
}
unlink(rb->shared_hdr->data_path);
unlink(rb->shared_hdr->hdr_path);
qb_util_log(LOG_DEBUG,
@ -262,7 +285,9 @@ qb_rb_force_close(struct qb_ringbuffer_s * rb)
return;
}
(void)rb->sem_destroy_fn(rb);
if (rb->sem_destroy_fn) {
(void)rb->sem_destroy_fn(rb);
}
unlink(rb->shared_hdr->data_path);
unlink(rb->shared_hdr->hdr_path);
qb_util_log(LOG_DEBUG,
@ -311,9 +336,6 @@ qb_rb_space_free(struct qb_ringbuffer_s * rb)
return -EINVAL;
}
write_size = rb->shared_hdr->write_pt;
/*
* TODO idx_cache_line_step (write_size);
*/
read_size = rb->shared_hdr->read_pt;
if (write_size > read_size) {
@ -322,7 +344,11 @@ qb_rb_space_free(struct qb_ringbuffer_s * rb)
} else if (write_size < read_size) {
space_free = (read_size - write_size) - 1;
} else {
space_free = rb->shared_hdr->word_size;
if (rb->sem_getvalue_fn && rb->sem_getvalue_fn(rb) > 0) {
space_free = 0;
} else {
space_free = rb->shared_hdr->word_size;
}
}
/* word -> bytes */
@ -360,7 +386,11 @@ qb_rb_chunks_used(struct qb_ringbuffer_s *rb)
if (rb == NULL) {
return -EINVAL;
}
return rb->sem_getvalue_fn(rb);
if (rb->sem_getvalue_fn) {
return rb->sem_getvalue_fn(rb);
} else {
return -ENOTSUP;
}
}
void *
@ -369,6 +399,7 @@ qb_rb_chunk_alloc(struct qb_ringbuffer_s * rb, size_t len)
uint32_t write_pt;
if (rb == NULL) {
errno = EINVAL;
return NULL;
}
/*
@ -376,7 +407,7 @@ qb_rb_chunk_alloc(struct qb_ringbuffer_s * rb, size_t len)
*/
if (rb->flags & QB_RB_FLAG_OVERWRITE) {
while (qb_rb_space_free(rb) < (len + QB_RB_CHUNK_MARGIN)) {
qb_rb_chunk_reclaim(rb);
_rb_chunk_reclaim(rb);
}
} else {
if (qb_rb_space_free(rb) < (len + QB_RB_CHUNK_MARGIN)) {
@ -389,15 +420,13 @@ qb_rb_chunk_alloc(struct qb_ringbuffer_s * rb, size_t len)
/*
* insert the chunk header
*/
rb->shared_data[write_pt++] = 0;
idx_step(write_pt);
rb->shared_data[write_pt++] = QB_RB_CHUNK_MAGIC;
idx_step(write_pt);
rb->shared_data[write_pt] = 0;
QB_RB_CHUNK_MAGIC_SET(rb, write_pt, QB_RB_CHUNK_MAGIC_ALLOC);
/*
* return a pointer to the beginning of the chunk data
*/
return (void *)&rb->shared_data[write_pt];
return (void *)QB_RB_CHUNK_DATA_GET(rb, write_pt);
}
@ -409,14 +438,13 @@ qb_rb_chunk_step(struct qb_ringbuffer_s * rb, uint32_t pointer)
* skip over the chunk header
*/
pointer += QB_RB_CHUNK_HEADER_WORDS;
idx_step(pointer);
/*
* skip over the user's data.
*/
pointer += (chunk_size / sizeof(uint32_t));
/* make allowance for non-word sizes */
if ((chunk_size % sizeof(uint32_t)) != 0) {
if ((chunk_size % (sizeof(uint32_t) * QB_RB_WORD_ALIGN)) != 0) {
pointer++;
}
@ -437,21 +465,28 @@ qb_rb_chunk_commit(struct qb_ringbuffer_s * rb, size_t len)
*/
old_write_pt = rb->shared_hdr->write_pt;
rb->shared_data[old_write_pt] = len;
rb->shared_data[old_write_pt + 1] = QB_RB_CHUNK_MAGIC;
/*
* commit the new write pointer
*/
rb->shared_hdr->write_pt = qb_rb_chunk_step(rb, old_write_pt);
QB_RB_CHUNK_MAGIC_SET(rb, old_write_pt, QB_RB_CHUNK_MAGIC);
DEBUG_PRINTF("%s: read: %u, write: %u (was:%u)\n", __func__,
rb->shared_hdr->read_pt, rb->shared_hdr->write_pt,
old_write_pt);
DEBUG_PRINTF("commit [%zd] read: %u, write: %u -> %u (%u)\n",
(rb->sem_getvalue_fn ? rb->sem_getvalue_fn(rb) : 0),
rb->shared_hdr->read_pt,
old_write_pt,
rb->shared_hdr->write_pt,
rb->shared_hdr->word_size);
/*
* post the notification to the reader
*/
return rb->sem_post_fn(rb);
if (rb->sem_post_fn) {
return rb->sem_post_fn(rb);
} else {
return 0;
}
}
ssize_t
@ -478,59 +513,85 @@ qb_rb_chunk_write(struct qb_ringbuffer_s * rb, const void *data, size_t len)
return len;
}
void
qb_rb_chunk_reclaim(struct qb_ringbuffer_s * rb)
static void
_rb_chunk_reclaim(struct qb_ringbuffer_s * rb)
{
uint32_t old_read_pt;
uint32_t new_read_pt;
uint32_t chunk_magic;
if (rb == NULL || qb_rb_space_used(rb) == 0) {
old_read_pt = rb->shared_hdr->read_pt;
chunk_magic = QB_RB_CHUNK_MAGIC_GET(rb, old_read_pt);
if (chunk_magic != QB_RB_CHUNK_MAGIC) {
return;
}
old_read_pt = rb->shared_hdr->read_pt;
qb_rb_chunk_check(rb, old_read_pt);
rb->shared_hdr->read_pt = qb_rb_chunk_step(rb, old_read_pt);
new_read_pt = qb_rb_chunk_step(rb, old_read_pt);
/*
* clear the header
*/
rb->shared_data[old_read_pt] = 0;
rb->shared_data[old_read_pt + 1] = 0;
QB_RB_CHUNK_MAGIC_SET(rb, old_read_pt, QB_RB_CHUNK_MAGIC_DEAD);
DEBUG_PRINTF("%s: read: %u (was:%u), write: %u\n", __func__,
rb->shared_hdr->read_pt, old_read_pt,
/*
* set the new read pointer after clearing the header
* to prevent a situation where a fast writer will write their
* new chunk between setting the new read pointer and clearing the
* header.
*/
rb->shared_hdr->read_pt = new_read_pt;
DEBUG_PRINTF("reclaim [%zd]: read: %u -> %u, write: %u\n",
(rb->sem_getvalue_fn ? rb->sem_getvalue_fn(rb) : 0),
old_read_pt,
rb->shared_hdr->read_pt,
rb->shared_hdr->write_pt);
}
void
qb_rb_chunk_reclaim(struct qb_ringbuffer_s * rb)
{
if (rb == NULL) {
return;
}
_rb_chunk_reclaim(rb);
}
ssize_t
qb_rb_chunk_peek(struct qb_ringbuffer_s * rb, void **data_out, int32_t timeout)
{
uint32_t read_pt;
uint32_t chunk_size;
uint32_t chunk_magic;
int32_t res;
int32_t res = 0;
if (rb == NULL) {
return -EINVAL;
}
res = rb->sem_timedwait_fn(rb, timeout);
if (rb->sem_timedwait_fn) {
res = rb->sem_timedwait_fn(rb, timeout);
}
if (res < 0 && res != -EIDRM) {
if (res != -ETIMEDOUT) {
if (res == -ETIMEDOUT) {
return 0;
} else {
errno = -res;
qb_util_perror(LOG_ERR, "sem_timedwait");
}
return res;
}
read_pt = rb->shared_hdr->read_pt;
chunk_size = QB_RB_CHUNK_SIZE_GET(rb, read_pt);
chunk_magic = QB_RB_CHUNK_MAGIC_GET(rb, read_pt);
*data_out = &rb->shared_data[read_pt + QB_RB_CHUNK_HEADER_WORDS];
if (chunk_magic != QB_RB_CHUNK_MAGIC) {
errno = ENOMSG;
if (rb->sem_post_fn) {
(void)rb->sem_post_fn(rb);
}
return 0;
} else {
return chunk_size;
}
chunk_size = QB_RB_CHUNK_SIZE_GET(rb, read_pt);
*data_out = QB_RB_CHUNK_DATA_GET(rb, read_pt);
return chunk_size;
}
ssize_t
@ -539,6 +600,7 @@ qb_rb_chunk_read(struct qb_ringbuffer_s * rb, void *data_out, size_t len,
{
uint32_t read_pt;
uint32_t chunk_size;
uint32_t chunk_magic;
int32_t res = 0;
if (rb == NULL) {
@ -554,26 +616,36 @@ qb_rb_chunk_read(struct qb_ringbuffer_s * rb, void *data_out, size_t len,
return res;
}
if (qb_rb_space_used(rb) == 0) {
return -ENOMSG;
read_pt = rb->shared_hdr->read_pt;
chunk_magic = QB_RB_CHUNK_MAGIC_GET(rb, read_pt);
if (chunk_magic != QB_RB_CHUNK_MAGIC) {
if (rb->sem_timedwait_fn == NULL) {
return -ETIMEDOUT;
} else {
(void)rb->sem_post_fn(rb);
#ifdef EBADMSG
return -EBADMSG;
#else
return -EINVAL;
#endif
}
}
read_pt = rb->shared_hdr->read_pt;
qb_rb_chunk_check(rb, read_pt);
chunk_size = QB_RB_CHUNK_SIZE_GET(rb, read_pt);
if (len < chunk_size) {
qb_util_log(LOG_ERR,
"trying to recv chunk of size %d but %d available",
len, chunk_size);
(void)rb->sem_post_fn(rb);
return -ENOBUFS;
}
;
memcpy(data_out,
&rb->shared_data[read_pt + QB_RB_CHUNK_HEADER_WORDS],
QB_RB_CHUNK_DATA_GET(rb, read_pt),
chunk_size);
qb_rb_chunk_reclaim(rb);
_rb_chunk_reclaim(rb);
return chunk_size;
}
@ -596,21 +668,6 @@ print_header(struct qb_ringbuffer_s * rb)
#endif /* S_SPLINT_S */
}
static void
qb_rb_chunk_check(struct qb_ringbuffer_s * rb, uint32_t pointer)
{
uint32_t chunk_size;
uint32_t chunk_magic = QB_RB_CHUNK_MAGIC_GET(rb, pointer);
if (chunk_magic != QB_RB_CHUNK_MAGIC) {
chunk_size = QB_RB_CHUNK_SIZE_GET(rb, pointer);
printf("size: %x\n", chunk_size);
printf("magic: %x\n", chunk_magic);
print_header(rb);
assert(0);
}
}
ssize_t
qb_rb_write_to_file(struct qb_ringbuffer_s * rb, int32_t fd)
{
@ -628,13 +685,6 @@ qb_rb_write_to_file(struct qb_ringbuffer_s * rb, int32_t fd)
}
written_size += result;
result = write(fd, rb->shared_data,
rb->shared_hdr->word_size * sizeof(uint32_t));
if (result != rb->shared_hdr->word_size * sizeof(uint32_t)) {
return -errno;
}
written_size += result;
/*
* store the read & write pointers
*/
@ -649,6 +699,13 @@ qb_rb_write_to_file(struct qb_ringbuffer_s * rb, int32_t fd)
}
written_size += result;
result = write(fd, rb->shared_data,
rb->shared_hdr->word_size * sizeof(uint32_t));
if (result != rb->shared_hdr->word_size * sizeof(uint32_t)) {
return -errno;
}
written_size += result;
qb_util_log(LOG_DEBUG, " writing total of: %zd\n", written_size);
return written_size;
@ -663,35 +720,37 @@ qb_rb_create_from_file(int32_t fd, uint32_t flags)
uint32_t read_pt;
uint32_t write_pt;
struct qb_ringbuffer_s *rb;
uint32_t word_size = 0;
if (fd < 0) {
return NULL;
}
rb = calloc(1, sizeof(struct qb_ringbuffer_s));
if (rb == NULL) {
return NULL;
}
rb->shared_hdr = calloc(1, sizeof(struct qb_ringbuffer_shared_s));
if (rb->shared_hdr == NULL) {
goto cleanup_fail2;
}
rb->flags = flags;
n_required = sizeof(uint32_t);
n_read = read(fd, &rb->shared_hdr->word_size, n_required);
n_read = read(fd, &word_size, n_required);
if (n_read != n_required) {
qb_util_perror(LOG_ERR, "Unable to read blackbox file header");
goto cleanup_fail;
return NULL;
}
total_read += n_read;
n_required = (rb->shared_hdr->word_size * sizeof(uint32_t));
n_read = read(fd, &write_pt, sizeof(uint32_t));
assert(n_read == sizeof(uint32_t));
total_read += n_read;
if ((rb->shared_data = malloc(n_required)) == NULL) {
qb_util_perror(LOG_ERR, "exhausted virtual memory");
goto cleanup_fail;
n_read = read(fd, &read_pt, sizeof(uint32_t));
assert(n_read == sizeof(uint32_t));
total_read += n_read;
n_required = (word_size * sizeof(uint32_t));
rb = qb_rb_open("create_from_file", n_required,
QB_RB_FLAG_CREATE | QB_RB_FLAG_NO_SEMAPHORE, 0);
if (rb == NULL) {
return NULL;
}
rb->shared_hdr->read_pt = read_pt;
rb->shared_hdr->write_pt = write_pt;
n_read = read(fd, rb->shared_data, n_required);
if (n_read < 0) {
qb_util_perror(LOG_ERR, "Unable to read blackbox file data");
@ -705,25 +764,13 @@ qb_rb_create_from_file(int32_t fd, uint32_t flags)
goto cleanup_fail;
}
n_read = read(fd, &write_pt, sizeof(uint32_t));
assert(n_read == sizeof(uint32_t));
rb->shared_hdr->write_pt = write_pt;
total_read += n_read;
n_read = read(fd, &read_pt, sizeof(uint32_t));
assert(n_read == sizeof(uint32_t));
rb->shared_hdr->read_pt = read_pt;
total_read += n_read;
qb_util_log(LOG_DEBUG, "read total of: %zd", total_read);
print_header(rb);
return rb;
cleanup_fail:
free(rb->shared_hdr);
cleanup_fail2:
free(rb);
qb_rb_close(rb);
return NULL;
}
@ -736,10 +783,29 @@ qb_rb_chown(struct qb_ringbuffer_s * rb, uid_t owner, gid_t group)
return -EINVAL;
}
res = chown(rb->shared_hdr->data_path, owner, group);
if (res < 0) {
if (res < 0 && errno != EPERM) {
return -errno;
}
res = chown(rb->shared_hdr->hdr_path, owner, group);
if (res < 0 && errno != EPERM) {
return -errno;
}
return 0;
}
int32_t
qb_rb_chmod(qb_ringbuffer_t * rb, mode_t mode)
{
int32_t res;
if (rb == NULL) {
return -EINVAL;
}
res = chmod(rb->shared_hdr->data_path, mode);
if (res < 0) {
return -errno;
}
res = chmod(rb->shared_hdr->hdr_path, mode);
if (res < 0) {
return -errno;
}

View File

@ -34,11 +34,11 @@ my_posix_sem_timedwait(qb_ringbuffer_t * rb, int32_t ms_timeout)
sem_wait_again:
if (ms_timeout > 0) {
res = sem_timedwait(&rb->shared_hdr->posix_sem, &ts_timeout);
res = rpl_sem_timedwait(&rb->shared_hdr->posix_sem, &ts_timeout);
} else if (ms_timeout == 0) {
res = sem_trywait(&rb->shared_hdr->posix_sem);
res = rpl_sem_trywait(&rb->shared_hdr->posix_sem);
} else {
res = sem_wait(&rb->shared_hdr->posix_sem);
res = rpl_sem_wait(&rb->shared_hdr->posix_sem);
}
if (res == -1) {
switch (errno) {
@ -63,7 +63,7 @@ sem_wait_again:
static int32_t
my_posix_sem_post(qb_ringbuffer_t * rb)
{
if (sem_post(&rb->shared_hdr->posix_sem) < 0) {
if (rpl_sem_post(&rb->shared_hdr->posix_sem) < 0) {
return -errno;
} else {
return 0;
@ -74,7 +74,7 @@ static ssize_t
my_posix_getvalue_fn(struct qb_ringbuffer_s *rb)
{
int val;
if (sem_getvalue(&rb->shared_hdr->posix_sem, &val) < 0) {
if (rpl_sem_getvalue(&rb->shared_hdr->posix_sem, &val) < 0) {
return -errno;
} else {
return val;
@ -84,7 +84,7 @@ my_posix_getvalue_fn(struct qb_ringbuffer_s *rb)
static int32_t
my_posix_sem_destroy(qb_ringbuffer_t * rb)
{
if (sem_destroy(&rb->shared_hdr->posix_sem) == -1) {
if (rpl_sem_destroy(&rb->shared_hdr->posix_sem) == -1) {
return -errno;
} else {
return 0;
@ -101,20 +101,19 @@ my_posix_sem_create(struct qb_ringbuffer_s *rb, uint32_t flags)
}
pshared = 1;
}
if (sem_init(&rb->shared_hdr->posix_sem, pshared, 0) == -1) {
if (rpl_sem_init(&rb->shared_hdr->posix_sem, pshared, 0) == -1) {
return -errno;
} else {
return 0;
}
}
#ifndef HAVE_POSIX_SHARED_SEMAPHORE
static int32_t
my_sysv_sem_timedwait(qb_ringbuffer_t * rb, int32_t ms_timeout)
{
struct sembuf sops[1];
int32_t res = 0;
#ifndef QB_FREEBSD_GE_8
#ifdef HAVE_SEMTIMEDOP
struct timespec ts_timeout;
struct timespec *ts_pt;
@ -130,25 +129,25 @@ my_sysv_sem_timedwait(qb_ringbuffer_t * rb, int32_t ms_timeout)
} else {
ts_pt = NULL;
}
#endif /* bsd */
#endif /* HAVE_SEMTIMEDOP */
/*
* wait for sem post.
*/
sops[0].sem_num = 0;
sops[0].sem_op = -1;
#ifdef QB_FREEBSD_GE_8
sops[0].sem_flg = IPC_NOWAIT;
#else
#ifdef HAVE_SEMTIMEDOP
sops[0].sem_flg = 0;
#endif /* bsd */
#else
sops[0].sem_flg = IPC_NOWAIT;
#endif /* HAVE_SEMTIMEDOP */
semop_again:
#ifdef QB_FREEBSD_GE_8
if (semop(rb->sem_id, sops, 1) == -1)
#else
#ifdef HAVE_SEMTIMEDOP
if (semtimedop(rb->sem_id, sops, 1, ts_pt) == -1)
#endif
#else
if (semop(rb->sem_id, sops, 1) == -1)
#endif /* HAVE_SEMTIMEDOP */
{
if (errno == EINTR) {
goto semop_again;
@ -249,25 +248,44 @@ my_sysv_sem_create(qb_ringbuffer_t * rb, uint32_t flags)
return res;
}
#endif /* NOT HAVE_POSIX_SHARED_SEMAPHORE */
int32_t
qb_rb_sem_create(struct qb_ringbuffer_s * rb, uint32_t flags)
{
#ifndef HAVE_POSIX_SHARED_SEMAPHORE
if (rb->flags & QB_RB_FLAG_SHARED_PROCESS) {
rb->sem_timedwait_fn = my_sysv_sem_timedwait;
rb->sem_post_fn = my_sysv_sem_post;
rb->sem_getvalue_fn = my_sysv_getvalue_fn;
rb->sem_destroy_fn = my_sysv_sem_destroy;
return my_sysv_sem_create(rb, flags);
} else
#endif /* NOT HAVE_POSIX_SHARED_SEMAPHORE */
{
int32_t rc;
int32_t use_posix = QB_TRUE;
if ((flags & QB_RB_FLAG_SHARED_PROCESS) &&
!(flags & QB_RB_FLAG_NO_SEMAPHORE)) {
#if defined(HAVE_POSIX_PSHARED_SEMAPHORE) || \
defined(HAVE_RPL_PSHARED_SEMAPHORE)
use_posix = QB_TRUE;
#else
#ifdef HAVE_SYSV_PSHARED_SEMAPHORE
use_posix = QB_FALSE;
#else
return -ENOTSUP;
#endif /* HAVE_SYSV_PSHARED_SEMAPHORE */
#endif /* HAVE_POSIX_PSHARED_SEMAPHORE */
}
if (flags & QB_RB_FLAG_NO_SEMAPHORE) {
rc = 0;
rb->sem_timedwait_fn = NULL;
rb->sem_post_fn = NULL;
rb->sem_getvalue_fn = NULL;
rb->sem_destroy_fn = NULL;
} else if (use_posix) {
rc = my_posix_sem_create(rb, flags);
rb->sem_timedwait_fn = my_posix_sem_timedwait;
rb->sem_post_fn = my_posix_sem_post;
rb->sem_getvalue_fn = my_posix_getvalue_fn;
rb->sem_destroy_fn = my_posix_sem_destroy;
return my_posix_sem_create(rb, flags);
} else {
rc = my_sysv_sem_create(rb, flags);
rb->sem_timedwait_fn = my_sysv_sem_timedwait;
rb->sem_post_fn = my_sysv_sem_post;
rb->sem_getvalue_fn = my_sysv_getvalue_fn;
rb->sem_destroy_fn = my_sysv_sem_destroy;
}
return rc;
}

View File

@ -32,9 +32,7 @@
#ifdef HAVE_SYS_IPC_H
#include <sys/ipc.h>
#endif
#include <pthread.h>
#include <semaphore.h>
#include "rpl_sem.h"
#include "util_int.h"
#include <qb/qbutil.h>
#include <qb/qbrb.h>
@ -55,9 +53,9 @@ struct qb_ringbuffer_shared_s {
char hdr_path[PATH_MAX];
char data_path[PATH_MAX];
int32_t ref_count;
sem_t posix_sem;
rpl_sem_t posix_sem;
char user_data[1];
};
} __attribute__ ((aligned(8)));
struct qb_ringbuffer_s {
uint32_t flags;
@ -74,13 +72,13 @@ struct qb_ringbuffer_s {
void qb_rb_force_close(qb_ringbuffer_t * rb);
#if defined(_SEM_SEMUN_UNDEFINED)
#ifndef HAVE_SEMUN
union semun {
int32_t val;
struct semid_ds *buf;
unsigned short int *array;
struct seminfo *__buf;
};
#endif /* _SEM_SEMUN_UNDEFINED */
#endif /* HAVE_SEMUN */
#endif /* _RINGBUFFER_H_ */

190
lib/rpl_sem.c Normal file
View File

@ -0,0 +1,190 @@
/*
* Copyright (C) 2007 Pingtel Corp., certain elements licensed under a Contributor Agreement.
* Contributors retain copyright to elements licensed under a Contributor Agreement.
* Licensed to the User under the LGPL license.
*
* Modified by: Angus Salkeld <asalkeld@redhat.com>
* Copyright (C) 2012 Red Hat, Inc.
* To conform to posix API and support process shared semaphores.
*
* The bsd posix semaphore implementation does not have support for timing
* out while waiting for a synchronization object. This uses the
* pthread_cond_timedwait function and a mutex to build all the other
* synchronization objecs with timeout capabilities.
*/
#include "os_base.h"
#include <pthread.h>
#include "rpl_sem.h"
int
rpl_sem_init(rpl_sem_t * sem, int pshared, unsigned int count)
{
int rc;
pthread_mutexattr_t mattr;
pthread_condattr_t cattr;
#ifndef HAVE_RPL_PSHARED_SEMAPHORE
if (pshared) {
errno = ENOSYS;
return -1;
}
#endif /* HAVE_RPL_PSHARED_SEMAPHORE */
sem->count = count;
(void)pthread_mutexattr_init(&mattr);
(void)pthread_condattr_init(&cattr);
#ifdef HAVE_RPL_PSHARED_SEMAPHORE
if (pshared) {
rc = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
if (rc != 0) {
goto cleanup;
}
rc = pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);
if (rc != 0) {
goto cleanup;
}
}
#endif /* HAVE_RPL_PSHARED_SEMAPHORE */
rc = pthread_mutex_init(&sem->mutex, &mattr);
if (rc != 0) {
goto cleanup;
}
rc = pthread_cond_init(&sem->cond, &cattr);
if (rc != 0) {
goto cleanup_mutex;
}
return 0;
cleanup_mutex:
pthread_mutex_destroy(&sem->mutex);
cleanup:
pthread_mutexattr_destroy(&mattr);
pthread_condattr_destroy(&cattr);
return rc;
}
int
rpl_sem_wait(rpl_sem_t * sem)
{
int retval = pthread_mutex_lock(&sem->mutex);
if (retval != 0) {
errno = retval;
return -1;
}
/* wait for sem->count to be not zero, or error
*/
while (retval == 0 && !sem->count) {
retval = pthread_cond_wait(&sem->cond, &sem->mutex);
}
switch (retval) {
case 0:
/* retval is 0 and sem->count is not, the sem is ours
*/
sem->count--;
break;
default:
errno = retval;
retval = -1;
}
pthread_mutex_unlock(&sem->mutex);
return retval;
}
int
rpl_sem_timedwait(rpl_sem_t * sem, const struct timespec *timeout)
{
int retval = pthread_mutex_lock(&sem->mutex);
if (retval != 0) {
errno = retval;
return -1;
}
/* wait for sem->count to be not zero, or error
*/
while (0 == retval && !sem->count) {
retval = pthread_cond_timedwait(&sem->cond, &sem->mutex, timeout);
}
switch (retval) {
case 0:
/* retval is 0 and sem->count is not, the sem is ours
*/
sem->count--;
break;
case ETIMEDOUT:
/* timedout waiting for count to be not zero
*/
errno = EAGAIN;
retval = -1;
break;
default:
errno = retval;
retval = -1;
}
pthread_mutex_unlock(&sem->mutex);
return retval;
}
int
rpl_sem_trywait(rpl_sem_t * sem)
{
int retval = pthread_mutex_lock(&sem->mutex);
if (retval != 0) {
errno = retval;
return -1;
}
if (sem->count) {
sem->count--;
pthread_mutex_unlock(&sem->mutex);
return 0;
}
errno = EAGAIN;
pthread_mutex_unlock(&sem->mutex);
return -1;
}
int
rpl_sem_post(rpl_sem_t * sem)
{
int retval = pthread_mutex_lock(&sem->mutex);
if (retval != 0) {
errno = retval;
return -1;
}
sem->count++;
retval = pthread_cond_broadcast(&sem->cond);
pthread_mutex_unlock(&sem->mutex);
if (retval != 0) {
errno = retval;
return -1;
}
return 0;
}
int
rpl_sem_getvalue(rpl_sem_t * sem, int *sval)
{
int retval = pthread_mutex_lock(&sem->mutex);
if (retval != 0) {
errno = retval;
return -1;
}
*sval = sem->count;
pthread_mutex_unlock(&sem->mutex);
return 0;
}
int
rpl_sem_destroy(rpl_sem_t * sem)
{
return pthread_mutex_destroy(&sem->mutex) |
pthread_cond_destroy(&sem->cond);
}

64
lib/rpl_sem.h Normal file
View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2007 Pingtel Corp., certain elements licensed under a Contributor Agreement.
* Contributors retain copyright to elements licensed under a Contributor Agreement.
* Licensed to the User under the LGPL license.
*
* Modified by: Angus Salkeld <asalkeld@redhat.com>
* Copyright (C) 2012 Red Hat, Inc.
* To conform to official implementation and support process shared semaphores.
*
* The bsd posix semaphore implementation does not have support for timing
* out while waiting for a synchronization object. This uses the
* pthread_cond_timedwait function and a mutex to build all the other
* synchronization objecs with timeout capabilities.
*/
#ifndef _RPL_SEM_H
#define _RPL_SEM_H
#include "os_base.h"
#include <pthread.h>
#include <semaphore.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef HAVE_SEM_TIMEDWAIT
#define rpl_sem_t sem_t
#define rpl_sem_init sem_init
#define rpl_sem_wait sem_wait
#define rpl_sem_timedwait sem_timedwait
#define rpl_sem_post sem_post
#define rpl_sem_getvalue sem_getvalue
#define rpl_sem_destroy sem_destroy
#define rpl_sem_trywait sem_trywait
#else
typedef struct rpl_sem {
unsigned int count;
pthread_mutex_t mutex;
pthread_cond_t cond;
} rpl_sem_t;
int rpl_sem_init(rpl_sem_t * sem, int pshared, unsigned int count);
int rpl_sem_wait(rpl_sem_t *sem);
int rpl_sem_timedwait(rpl_sem_t *sem,const struct timespec *timeout);
int rpl_sem_trywait(rpl_sem_t *sem);
int rpl_sem_post(rpl_sem_t *sem);
int rpl_sem_getvalue(rpl_sem_t * sem, int *sval);
int rpl_sem_destroy(rpl_sem_t *sem);
#endif /* HAVE_SEM_TIMEDWAIT */
#ifdef __cplusplus
}
#endif
#endif /* _RPL_SEM_H */

View File

@ -32,17 +32,25 @@
#include <qb/qbutil.h>
#include <qb/qbatomic.h>
#if defined(MAP_ANON) && ! defined(MAP_ANONYMOUS)
/*
* BSD derivatives usually have MAP_ANON, not MAP_ANONYMOUS
**/
#define MAP_ANONYMOUS MAP_ANON
#endif
char *
qb_strerror_r(int errnum, char *buf, size_t buflen)
{
#ifdef QB_LINUX
#ifdef STRERROR_R_CHAR_P
return strerror_r(errnum, buf, buflen);
#else
if (strerror_r(errnum, buf, buflen) != 0) {
buf[0] = '\0';
}
return buf;
#endif /* QB_LINUX */
#endif /* STRERROR_R_CHAR_P */
}
static int32_t
@ -72,7 +80,12 @@ qb_sys_mmap_file_open(char *path, const char *file, size_t bytes,
if (is_absolute) {
(void)strlcpy(path, file, PATH_MAX);
} else {
#if defined(QB_LINUX) || defined(QB_CYGWIN)
snprintf(path, PATH_MAX, "/dev/shm/%s", file);
#else
snprintf(path, PATH_MAX, LOCALSTATEDIR "/run/%s", file);
is_absolute = path;
#endif
}
fd = open_mmap_file(path, file_flags);
if (fd < 0 && !is_absolute) {
@ -85,6 +98,10 @@ qb_sys_mmap_file_open(char *path, const char *file, size_t bytes,
qb_util_perror(LOG_ERR, "couldn't open file %s", path);
return res;
}
} else if (fd < 0 && is_absolute) {
res = -errno;
qb_util_perror(LOG_ERR, "couldn't open file %s", path);
return res;
}
if (ftruncate(fd, bytes) == -1) {
@ -165,7 +182,7 @@ qb_sys_circular_mmap(int32_t fd, void **buf, size_t bytes)
res = -errno;
goto cleanup_fail;
}
#ifdef QB_BSD
#if defined(QB_BSD) && defined(MADV_NOSYNC)
madvise(addr_orig, bytes, MADV_NOSYNC);
#endif
addr_next = ((char *)addr_orig) + bytes;
@ -176,7 +193,7 @@ qb_sys_circular_mmap(int32_t fd, void **buf, size_t bytes)
res = -errno;
goto cleanup_fail;
}
#ifdef QB_BSD
#if defined(QB_BSD) && defined(MADV_NOSYNC)
madvise(((char *)addr_orig) + bytes, bytes, MADV_NOSYNC);
#endif

View File

@ -197,7 +197,7 @@ qb_util_nano_current_get(void)
uint64_t
qb_util_nano_monotonic_hz(void)
{
return HZ;
return sysconf(_SC_CLK_TCK);
}
void

View File

@ -34,7 +34,7 @@ make check
rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT
find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';'
rm -rf $RPM_BUILD_ROOT/%{_docdir}/*
rm -rf $RPM_BUILD_ROOT/%{_datadir}/doc/libqb
%clean
rm -rf $RPM_BUILD_ROOT
@ -46,6 +46,7 @@ rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root,-)
%doc COPYING
%{_sbindir}/qb-blackbox
%{_libdir}/libqb.so.*
%package devel
@ -64,6 +65,7 @@ developing applications that use %{name}.
%{_libdir}/libqb.so
%{_libdir}/pkgconfig/libqb.pc
%{_mandir}/man3/qb*3*
%{_mandir}/man8/qb-blackbox.8.gz
%changelog
* @date@ Autotools generated version <nobody@nowhere.org> - @version@-1-@numcomm@.@alphatag@.@dirty@

View File

@ -17,7 +17,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with libqb. If not, see <http://www.gnu.org/licenses/>.
#
MAINTAINERCLEANFILES = Makefiles.in
MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST =
CLEANFILES =
AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
@ -31,23 +31,23 @@ noinst_PROGRAMS = bmc bmcpt bms rbwriter rbreader loop bench-log \
bmc_SOURCES = bmc.c $(top_builddir)/include/qb/qbipcc.h
bmc_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
bmc_LDADD = $(top_builddir)/lib/libqb.la
bmcpt_SOURCES = bmcpt.c $(top_builddir)/include/qb/qbipcc.h
bmcpt_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
bmcpt_LDADD = $(top_builddir)/lib/libqb.la
bms_SOURCES = bms.c $(top_builddir)/include/qb/qbipcs.h
bms_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include $(GLIB_CFLAGS)
bms_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la $(GLIB_LIBS)
bms_LDADD = $(top_builddir)/lib/libqb.la $(GLIB_LIBS)
rbwriter_SOURCES = rbwriter.c $(top_builddir)/include/qb/qbrb.h
rbwriter_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
rbwriter_LDADD = $(top_builddir)/lib/libqb.la
rbreader_SOURCES = rbreader.c $(top_builddir)/include/qb/qbrb.h
rbreader_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
rbreader_LDADD = $(top_builddir)/lib/libqb.la
loop_SOURCES = loop.c $(top_builddir)/include/qb/qbloop.h
loop_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
loop_LDADD = $(top_builddir)/lib/libqb.la
public_headers = $(wildcard $(top_srcdir)/include/qb/qb*.h)
auto_c_files = $(patsubst %.h,auto_check_header_%.c,$(public_headers))
@ -84,7 +84,7 @@ endif
bench_log_SOURCES = bench-log.c $(top_builddir)/include/qb/qblog.h
bench_log_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
bench_log_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
bench_log_LDADD = $(top_builddir)/lib/libqb.la
if HAVE_CHECK
EXTRA_DIST += resources.test
@ -103,31 +103,31 @@ endif
array_test_SOURCES = check_array.c $(top_builddir)/include/qb/qbarray.h
array_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include
array_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@
array_test_LDADD = $(top_builddir)/lib/libqb.la @CHECK_LIBS@
map_test_SOURCES = check_map.c $(top_builddir)/include/qb/qbmap.h
map_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include
map_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@
map_test_LDADD = $(top_builddir)/lib/libqb.la @CHECK_LIBS@
rb_test_SOURCES = check_rb.c $(top_builddir)/include/qb/qbrb.h
rb_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include
rb_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@
rb_test_LDADD = $(top_builddir)/lib/libqb.la @CHECK_LIBS@
loop_test_SOURCES = check_loop.c $(top_builddir)/include/qb/qbloop.h
loop_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include
loop_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@
loop_test_LDADD = $(top_builddir)/lib/libqb.la @CHECK_LIBS@
ipc_test_SOURCES = check_ipc.c $(top_builddir)/include/qb/qbipcc.h $(top_builddir)/include/qb/qbipcs.h
ipc_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include
ipc_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@
ipc_test_LDADD = $(top_builddir)/lib/libqb.la @CHECK_LIBS@
log_test_SOURCES = check_log.c $(top_builddir)/include/qb/qblog.h
log_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include
log_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@
log_test_LDADD = $(top_builddir)/lib/libqb.la @CHECK_LIBS@
util_test_SOURCES = check_util.c $(top_builddir)/include/qb/qbutil.h
util_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include
util_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@
util_test_LDADD = $(top_builddir)/lib/libqb.la @CHECK_LIBS@
endif

View File

@ -87,10 +87,8 @@ am__array_test_SOURCES_DIST = check_array.c \
@HAVE_CHECK_TRUE@am_array_test_OBJECTS = \
@HAVE_CHECK_TRUE@ array_test-check_array.$(OBJEXT)
array_test_OBJECTS = $(am_array_test_OBJECTS)
am__DEPENDENCIES_1 =
@HAVE_CHECK_TRUE@array_test_DEPENDENCIES = \
@HAVE_CHECK_TRUE@ $(top_builddir)/lib/libqb.la \
@HAVE_CHECK_TRUE@ $(am__DEPENDENCIES_1)
@HAVE_CHECK_TRUE@ $(top_builddir)/lib/libqb.la
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
@ -148,26 +146,23 @@ am_bench_log_OBJECTS = bench_log-bench-log.$(OBJEXT)
@HAVE_DICT_WORDS_TRUE@@HAVE_SLOW_TESTS_TRUE@nodist_bench_log_OBJECTS = bench_log-auto_write_logs.$(OBJEXT)
bench_log_OBJECTS = $(am_bench_log_OBJECTS) \
$(nodist_bench_log_OBJECTS)
bench_log_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(top_builddir)/lib/libqb.la
bench_log_DEPENDENCIES = $(top_builddir)/lib/libqb.la
am_bmc_OBJECTS = bmc.$(OBJEXT)
bmc_OBJECTS = $(am_bmc_OBJECTS)
bmc_DEPENDENCIES = $(am__DEPENDENCIES_1) $(top_builddir)/lib/libqb.la
bmc_DEPENDENCIES = $(top_builddir)/lib/libqb.la
am_bmcpt_OBJECTS = bmcpt.$(OBJEXT)
bmcpt_OBJECTS = $(am_bmcpt_OBJECTS)
bmcpt_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(top_builddir)/lib/libqb.la
bmcpt_DEPENDENCIES = $(top_builddir)/lib/libqb.la
am_bms_OBJECTS = bms-bms.$(OBJEXT)
bms_OBJECTS = $(am_bms_OBJECTS)
bms_DEPENDENCIES = $(am__DEPENDENCIES_1) $(top_builddir)/lib/libqb.la \
$(am__DEPENDENCIES_1)
am__DEPENDENCIES_1 =
bms_DEPENDENCIES = $(top_builddir)/lib/libqb.la $(am__DEPENDENCIES_1)
am__ipc_test_SOURCES_DIST = check_ipc.c \
$(top_builddir)/include/qb/qbipcc.h \
$(top_builddir)/include/qb/qbipcs.h
@HAVE_CHECK_TRUE@am_ipc_test_OBJECTS = ipc_test-check_ipc.$(OBJEXT)
ipc_test_OBJECTS = $(am_ipc_test_OBJECTS)
@HAVE_CHECK_TRUE@ipc_test_DEPENDENCIES = $(top_builddir)/lib/libqb.la \
@HAVE_CHECK_TRUE@ $(am__DEPENDENCIES_1)
@HAVE_CHECK_TRUE@ipc_test_DEPENDENCIES = $(top_builddir)/lib/libqb.la
ipc_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ipc_test_CFLAGS) \
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
@ -175,22 +170,20 @@ am__log_test_SOURCES_DIST = check_log.c \
$(top_builddir)/include/qb/qblog.h
@HAVE_CHECK_TRUE@am_log_test_OBJECTS = log_test-check_log.$(OBJEXT)
log_test_OBJECTS = $(am_log_test_OBJECTS)
@HAVE_CHECK_TRUE@log_test_DEPENDENCIES = $(top_builddir)/lib/libqb.la \
@HAVE_CHECK_TRUE@ $(am__DEPENDENCIES_1)
@HAVE_CHECK_TRUE@log_test_DEPENDENCIES = $(top_builddir)/lib/libqb.la
log_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(log_test_CFLAGS) \
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
am_loop_OBJECTS = loop.$(OBJEXT)
loop_OBJECTS = $(am_loop_OBJECTS)
loop_DEPENDENCIES = $(am__DEPENDENCIES_1) $(top_builddir)/lib/libqb.la
loop_DEPENDENCIES = $(top_builddir)/lib/libqb.la
am__loop_test_SOURCES_DIST = check_loop.c \
$(top_builddir)/include/qb/qbloop.h
@HAVE_CHECK_TRUE@am_loop_test_OBJECTS = \
@HAVE_CHECK_TRUE@ loop_test-check_loop.$(OBJEXT)
loop_test_OBJECTS = $(am_loop_test_OBJECTS)
@HAVE_CHECK_TRUE@loop_test_DEPENDENCIES = \
@HAVE_CHECK_TRUE@ $(top_builddir)/lib/libqb.la \
@HAVE_CHECK_TRUE@ $(am__DEPENDENCIES_1)
@HAVE_CHECK_TRUE@ $(top_builddir)/lib/libqb.la
loop_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(loop_test_CFLAGS) \
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
@ -198,8 +191,7 @@ am__map_test_SOURCES_DIST = check_map.c \
$(top_builddir)/include/qb/qbmap.h
@HAVE_CHECK_TRUE@am_map_test_OBJECTS = map_test-check_map.$(OBJEXT)
map_test_OBJECTS = $(am_map_test_OBJECTS)
@HAVE_CHECK_TRUE@map_test_DEPENDENCIES = $(top_builddir)/lib/libqb.la \
@HAVE_CHECK_TRUE@ $(am__DEPENDENCIES_1)
@HAVE_CHECK_TRUE@map_test_DEPENDENCIES = $(top_builddir)/lib/libqb.la
map_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(map_test_CFLAGS) \
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
@ -207,32 +199,28 @@ am__rb_test_SOURCES_DIST = check_rb.c \
$(top_builddir)/include/qb/qbrb.h
@HAVE_CHECK_TRUE@am_rb_test_OBJECTS = rb_test-check_rb.$(OBJEXT)
rb_test_OBJECTS = $(am_rb_test_OBJECTS)
@HAVE_CHECK_TRUE@rb_test_DEPENDENCIES = $(top_builddir)/lib/libqb.la \
@HAVE_CHECK_TRUE@ $(am__DEPENDENCIES_1)
@HAVE_CHECK_TRUE@rb_test_DEPENDENCIES = $(top_builddir)/lib/libqb.la
rb_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(rb_test_CFLAGS) \
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
am_rbreader_OBJECTS = rbreader.$(OBJEXT)
rbreader_OBJECTS = $(am_rbreader_OBJECTS)
rbreader_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(top_builddir)/lib/libqb.la
rbreader_DEPENDENCIES = $(top_builddir)/lib/libqb.la
am_rbwriter_OBJECTS = rbwriter.$(OBJEXT)
rbwriter_OBJECTS = $(am_rbwriter_OBJECTS)
rbwriter_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(top_builddir)/lib/libqb.la
rbwriter_DEPENDENCIES = $(top_builddir)/lib/libqb.la
am__util_test_SOURCES_DIST = check_util.c \
$(top_builddir)/include/qb/qbutil.h
@HAVE_CHECK_TRUE@am_util_test_OBJECTS = \
@HAVE_CHECK_TRUE@ util_test-check_util.$(OBJEXT)
util_test_OBJECTS = $(am_util_test_OBJECTS)
@HAVE_CHECK_TRUE@util_test_DEPENDENCIES = \
@HAVE_CHECK_TRUE@ $(top_builddir)/lib/libqb.la \
@HAVE_CHECK_TRUE@ $(am__DEPENDENCIES_1)
@HAVE_CHECK_TRUE@ $(top_builddir)/lib/libqb.la
util_test_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(util_test_CFLAGS) \
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include -I$(top_builddir)/include/qb
depcomp = $(SHELL) $(top_srcdir)/depcomp
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
@ -286,132 +274,8 @@ DIST_SOURCES = $(am__array_test_SOURCES_DIST) \
$(rbwriter_SOURCES) $(am__util_test_SOURCES_DIST)
ETAGS = etags
CTAGS = ctags
# If stdout is a non-dumb tty, use colors. If test -t is not supported,
# then this fails; a conservative approach. Of course do not redirect
# stdout here, just stderr.
am__tty_colors = \
red=; grn=; lgn=; blu=; std=; \
test "X$(AM_COLOR_TESTS)" != Xno \
&& test "X$$TERM" != Xdumb \
&& { test "X$(AM_COLOR_TESTS)" = Xalways || test -t 1 2>/dev/null; } \
&& { \
red=''; \
grn=''; \
lgn=''; \
blu=''; \
std=''; \
}
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
test -z "$$files" \
|| { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && rm -f $$files; }; \
}
# Restructured Text title and section.
am__rst_title = sed 's/.*/ & /;h;s/./=/g;p;x;p;g;p;s/.*//'
am__rst_section = sed 'p;s/./=/g;p;g'
# Put stdin (possibly several lines separated by ". ") in a box.
# Prefix each line by 'col' and terminate each with 'std', for coloring.
# Multi line coloring is problematic with "less -R", so we really need
# to color each line individually.
am__text_box = $(AWK) '{ \
n = split($$0, lines, "\\. "); max = 0; \
for (i = 1; i <= n; ++i) \
if (max < length(lines[i])) \
max = length(lines[i]); \
for (i = 0; i < max; ++i) \
line = line "="; \
print col line std; \
for (i = 1; i <= n; ++i) \
if (lines[i]) \
print col lines[i] std; \
print col line std; \
}'
# Solaris 10 'make', and several other traditional 'make' implementations,
# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
# by disabling -e (using the XSI extension "set +e") if it's set.
am__sh_e_setup = case $$- in *e*) set +e;; esac
# To be inserted before the command running the test. Creates the
# directory for the log if needed. Stores in $dir the directory
# containing $f, in $tst the test, in $log the log, and passes
# TESTS_ENVIRONMENT. Save and restore TERM around use of
# TESTS_ENVIRONMENT, in case that unsets it.
am__check_pre = \
$(am__sh_e_setup); \
$(am__vpath_adj_setup) $(am__vpath_adj) \
srcdir=$(srcdir); export srcdir; \
rm -f $@-t; \
am__trap='rm -f '\''$(abs_builddir)/$@-t'\''; (exit $$st); exit $$st'; \
trap "st=129; $$am__trap" 1; trap "st=130; $$am__trap" 2; \
trap "st=141; $$am__trap" 13; trap "st=143; $$am__trap" 15; \
am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`; \
test "x$$am__odir" = x. || $(MKDIR_P) "$$am__odir" || exit $$?; \
if test -f "./$$f"; then dir=./; \
elif test -f "$$f"; then dir=; \
else dir="$(srcdir)/"; fi; \
tst=$$dir$$f; log='$@'; __SAVED_TERM=$$TERM; \
$(TESTS_ENVIRONMENT)
# To be appended to the command running the test. Handle the stdout
# and stderr redirection, and catch the exit status.
am__check_post = \
>$@-t 2>&1; \
estatus=$$?; \
if test -n '$(DISABLE_HARD_ERRORS)' \
&& test $$estatus -eq 99; then \
estatus=1; \
fi; \
TERM=$$__SAVED_TERM; export TERM; \
$(am__tty_colors); \
xfailed=PASS; \
case " $(XFAIL_TESTS) " in \
*[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
xfailed=XFAIL;; \
esac; \
case $$estatus.$$xfailed in \
0.XFAIL) col=$$red; res=XPASS;; \
0.*) col=$$grn; res=PASS ;; \
77.*) col=$$blu; res=SKIP ;; \
99.*) col=$$red; res=FAIL ;; \
*.XFAIL) col=$$lgn; res=XFAIL;; \
*.*) col=$$red; res=FAIL ;; \
esac; \
echo "$${col}$$res$${std}: $$f"; \
echo "$$res: $$f (exit: $$estatus)" | \
$(am__rst_section) >$@; \
cat $@-t >>$@; \
rm -f $@-t
RECHECK_LOGS = $(TEST_LOGS)
AM_RECURSIVE_TARGETS = check recheck check-html recheck-html
TEST_SUITE_HTML = $(TEST_SUITE_LOG:.log=.html)
TEST_SUITE_LOG = test-suite.log
TEST_EXTENSIONS = @EXEEXT@ .test
am__test_logs1 = $(TESTS:=.log)
am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
TEST_LOGS = $(am__test_logs2:.test.log=.log)
TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
$(TEST_LOG_FLAGS)
TEST_LOGS_TMP = $(TEST_LOGS:.log=.log-t)
red=; grn=; lgn=; blu=; std=
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
@ -459,7 +323,6 @@ LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIB_RT = @LIB_RT@
LINT_FLAGS = @LINT_FLAGS@
LIPO = @LIPO@
LN_S = @LN_S@
@ -566,55 +429,55 @@ top_srcdir = @top_srcdir@
# You should have received a copy of the GNU Lesser General Public License
# along with libqb. If not, see <http://www.gnu.org/licenses/>.
#
MAINTAINERCLEANFILES = Makefiles.in $(auto_c_files) $(am__append_3)
MAINTAINERCLEANFILES = Makefile.in $(auto_c_files) $(am__append_3)
EXTRA_DIST = $(am__append_1) $(am__append_4)
CLEANFILES = $(auto_c_files) $(am__append_2)
AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
bmc_SOURCES = bmc.c $(top_builddir)/include/qb/qbipcc.h
bmc_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
bmc_LDADD = $(top_builddir)/lib/libqb.la
bmcpt_SOURCES = bmcpt.c $(top_builddir)/include/qb/qbipcc.h
bmcpt_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
bmcpt_LDADD = $(top_builddir)/lib/libqb.la
bms_SOURCES = bms.c $(top_builddir)/include/qb/qbipcs.h
bms_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include $(GLIB_CFLAGS)
bms_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la $(GLIB_LIBS)
bms_LDADD = $(top_builddir)/lib/libqb.la $(GLIB_LIBS)
rbwriter_SOURCES = rbwriter.c $(top_builddir)/include/qb/qbrb.h
rbwriter_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
rbwriter_LDADD = $(top_builddir)/lib/libqb.la
rbreader_SOURCES = rbreader.c $(top_builddir)/include/qb/qbrb.h
rbreader_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
rbreader_LDADD = $(top_builddir)/lib/libqb.la
loop_SOURCES = loop.c $(top_builddir)/include/qb/qbloop.h
loop_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
loop_LDADD = $(top_builddir)/lib/libqb.la
public_headers = $(wildcard $(top_srcdir)/include/qb/qb*.h)
auto_c_files = $(patsubst %.h,auto_check_header_%.c,$(public_headers))
@HAVE_DICT_WORDS_TRUE@@HAVE_SLOW_TESTS_TRUE@nodist_bench_log_SOURCES = auto_write_logs.c
bench_log_SOURCES = bench-log.c $(top_builddir)/include/qb/qblog.h
bench_log_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
bench_log_LDADD = $(LIB_RT) $(top_builddir)/lib/libqb.la
bench_log_LDADD = $(top_builddir)/lib/libqb.la
@HAVE_CHECK_TRUE@check_SCRIPTS = resources.test
@HAVE_CHECK_TRUE@array_test_SOURCES = check_array.c $(top_builddir)/include/qb/qbarray.h
@HAVE_CHECK_TRUE@array_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include
@HAVE_CHECK_TRUE@array_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@
@HAVE_CHECK_TRUE@array_test_LDADD = $(top_builddir)/lib/libqb.la @CHECK_LIBS@
@HAVE_CHECK_TRUE@map_test_SOURCES = check_map.c $(top_builddir)/include/qb/qbmap.h
@HAVE_CHECK_TRUE@map_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include
@HAVE_CHECK_TRUE@map_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@
@HAVE_CHECK_TRUE@map_test_LDADD = $(top_builddir)/lib/libqb.la @CHECK_LIBS@
@HAVE_CHECK_TRUE@rb_test_SOURCES = check_rb.c $(top_builddir)/include/qb/qbrb.h
@HAVE_CHECK_TRUE@rb_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include
@HAVE_CHECK_TRUE@rb_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@
@HAVE_CHECK_TRUE@rb_test_LDADD = $(top_builddir)/lib/libqb.la @CHECK_LIBS@
@HAVE_CHECK_TRUE@loop_test_SOURCES = check_loop.c $(top_builddir)/include/qb/qbloop.h
@HAVE_CHECK_TRUE@loop_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include
@HAVE_CHECK_TRUE@loop_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@
@HAVE_CHECK_TRUE@loop_test_LDADD = $(top_builddir)/lib/libqb.la @CHECK_LIBS@
@HAVE_CHECK_TRUE@ipc_test_SOURCES = check_ipc.c $(top_builddir)/include/qb/qbipcc.h $(top_builddir)/include/qb/qbipcs.h
@HAVE_CHECK_TRUE@ipc_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include
@HAVE_CHECK_TRUE@ipc_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@
@HAVE_CHECK_TRUE@ipc_test_LDADD = $(top_builddir)/lib/libqb.la @CHECK_LIBS@
@HAVE_CHECK_TRUE@log_test_SOURCES = check_log.c $(top_builddir)/include/qb/qblog.h
@HAVE_CHECK_TRUE@log_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include
@HAVE_CHECK_TRUE@log_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@
@HAVE_CHECK_TRUE@log_test_LDADD = $(top_builddir)/lib/libqb.la @CHECK_LIBS@
@HAVE_CHECK_TRUE@util_test_SOURCES = check_util.c $(top_builddir)/include/qb/qbutil.h
@HAVE_CHECK_TRUE@util_test_CFLAGS = @CHECK_CFLAGS@ -I$(top_srcdir)/include
@HAVE_CHECK_TRUE@util_test_LDADD = $(top_builddir)/lib/libqb.la $(LIB_RT) @CHECK_LIBS@
@HAVE_CHECK_TRUE@util_test_LDADD = $(top_builddir)/lib/libqb.la @CHECK_LIBS@
all: all-am
.SUFFIXES:
.SUFFIXES: .c .html .lo .log .o .obj .test .test$(EXEEXT)
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
@ -1000,137 +863,98 @@ GTAGS:
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
$(TEST_SUITE_LOG): $(TEST_LOGS)
@$(am__sh_e_setup); \
list='$(TEST_LOGS)'; \
results=`for f in $$list; do \
test -r $$f && read line < $$f && echo "$$line" \
|| echo FAIL; \
done`; \
all=`echo "$$results" | sed '/^$$/d' | wc -l | sed -e 's/^[ ]*//'`; \
fail=`echo "$$results" | grep -c '^FAIL'`; \
pass=`echo "$$results" | grep -c '^PASS'`; \
skip=`echo "$$results" | grep -c '^SKIP'`; \
xfail=`echo "$$results" | grep -c '^XFAIL'`; \
xpass=`echo "$$results" | grep -c '^XPASS'`; \
failures=`expr $$fail + $$xpass`; \
all=`expr $$all - $$skip`; \
if test "$$all" -eq 1; then tests=test; All=; \
else tests=tests; All="All "; fi; \
case fail=$$fail:xpass=$$xpass:xfail=$$xfail in \
fail=0:xpass=0:xfail=0) \
msg="$$All$$all $$tests passed. "; \
exit=true;; \
fail=0:xpass=0:xfail=*) \
msg="$$All$$all $$tests behaved as expected"; \
if test "$$xfail" -eq 1; then xfailures=failure; \
else xfailures=failures; fi; \
msg="$$msg ($$xfail expected $$xfailures). "; \
exit=true;; \
fail=*:xpass=0:xfail=*) \
msg="$$fail of $$all $$tests failed. "; \
exit=false;; \
fail=*:xpass=*:xfail=*) \
msg="$$failures of $$all $$tests did not behave as expected"; \
if test "$$xpass" -eq 1; then xpasses=pass; \
else xpasses=passes; fi; \
msg="$$msg ($$xpass unexpected $$xpasses). "; \
exit=false;; \
*) \
echo >&2 "incorrect case"; exit 4;; \
esac; \
if test "$$skip" -ne 0; then \
if test "$$skip" -eq 1; then \
msg="$$msg($$skip test was not run). "; \
else \
msg="$$msg($$skip tests were not run). "; \
fi; \
fi; \
{ \
echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
$(am__rst_title); \
echo "$$msg"; \
echo; \
echo ".. contents:: :depth: 2"; \
echo; \
for f in $$list; do \
test -r $$f && read line < $$f || line=; \
case $$line in \
PASS:*|XFAIL:*);; \
*) echo; cat $$f;; \
esac; \
done; \
} >$(TEST_SUITE_LOG).tmp; \
mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
if test "$$failures" -ne 0; then \
msg="$${msg}See $(subdir)/$(TEST_SUITE_LOG). "; \
if test -n "$(PACKAGE_BUGREPORT)"; then \
msg="$${msg}Please report to $(PACKAGE_BUGREPORT). "; \
fi; \
fi; \
test x"$$VERBOSE" = x || $$exit || cat $(TEST_SUITE_LOG); \
$(am__tty_colors); \
if $$exit; then \
col="$$grn"; \
else \
col="$$red"; \
fi; \
echo "$$msg" | $(am__text_box) "col=$$col" "std=$$std"; \
$$exit || exit 1
check-TESTS recheck:
@if test $@ != recheck; then \
list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list; \
fi
@test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
@list='' list2='$(TEST_LOGS)'; for f in $$list2; do \
test .log = $$f && continue; \
if test $@ = recheck; then \
test -f $$f || continue; \
if test -r $$f && read line < $$f; then \
case $$line in FAIL*|XPASS*) : ;; *) continue;; esac; \
check-TESTS: $(TESTS)
@failed=0; all=0; xfail=0; xpass=0; skip=0; \
srcdir=$(srcdir); export srcdir; \
list=' $(TESTS) '; \
$(am__tty_colors); \
if test -n "$$list"; then \
for tst in $$list; do \
if test -f ./$$tst; then dir=./; \
elif test -f $$tst; then dir=; \
else dir="$(srcdir)/"; fi; \
if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
all=`expr $$all + 1`; \
case " $(XFAIL_TESTS) " in \
*[\ \ ]$$tst[\ \ ]*) \
xpass=`expr $$xpass + 1`; \
failed=`expr $$failed + 1`; \
col=$$red; res=XPASS; \
;; \
*) \
col=$$grn; res=PASS; \
;; \
esac; \
elif test $$? -ne 77; then \
all=`expr $$all + 1`; \
case " $(XFAIL_TESTS) " in \
*[\ \ ]$$tst[\ \ ]*) \
xfail=`expr $$xfail + 1`; \
col=$$lgn; res=XFAIL; \
;; \
*) \
failed=`expr $$failed + 1`; \
col=$$red; res=FAIL; \
;; \
esac; \
else \
skip=`expr $$skip + 1`; \
col=$$blu; res=SKIP; \
fi; \
echo "$${col}$$res$${std}: $$tst"; \
done; \
if test "$$all" -eq 1; then \
tests="test"; \
All=""; \
else \
tests="tests"; \
All="All "; \
fi; \
if test "$$failed" -eq 0; then \
if test "$$xfail" -eq 0; then \
banner="$$All$$all $$tests passed"; \
else \
if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
fi; \
else \
if test "$$xpass" -eq 0; then \
banner="$$failed of $$all $$tests failed"; \
else \
if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
fi; \
fi; \
if test -z "$$list"; then list=$$f; else list="$$list $$f"; fi; \
done; \
if test $@ = recheck && test -n "$$list"; then \
echo "am--clean: ; rm -f $$list" \
| $(MAKE) $(AM_MAKEFLAGS) -f - am--clean || exit 1; \
fi; \
$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$list"
recheck: $(check_PROGRAMS) $(check_SCRIPTS)
am--mostlyclean-test-html:
list='$(TEST_LOGS:.log=.html)'; test -z "$$list" || rm -f $$list
rm -f $(TEST_SUITE_HTML)
.log.html:
@list='$(RST2HTML) $$RST2HTML rst2html rst2html.py'; \
for r2h in $$list; do \
if ($$r2h --version) >/dev/null 2>&1; then \
R2H=$$r2h; \
fi; \
done; \
if test -z "$$R2H"; then \
echo >&2 "cannot find rst2html, cannot create $@"; \
exit 2; \
fi; \
$$R2H $< >$@.tmp
@mv $@.tmp $@
# Be sure to run check first, and then to convert the result.
# Beware of concurrent executions. Run "check" not "check-TESTS", as
# check-SCRIPTS and other dependencies are rebuilt by the former only.
# And expect check to fail.
check-html recheck-html:
@target=`echo $@ | sed 's/-html$$//'`; \
rv=0; $(MAKE) $(AM_MAKEFLAGS) $$target || rv=$$?; \
$(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_HTML) TEST_LOGS= || exit 4; \
exit $$rv
.test.log:
@p='$<'; $(am__check_pre) $(TEST_LOG_COMPILE) "$$tst" $(am__check_post)
@am__EXEEXT_TRUE@.test$(EXEEXT).log:
@am__EXEEXT_TRUE@ @p='$<'; $(am__check_pre) $(TEST_LOG_COMPILE) "$$tst" $(am__check_post)
dashes="$$banner"; \
skipped=""; \
if test "$$skip" -ne 0; then \
if test "$$skip" -eq 1; then \
skipped="($$skip test was not run)"; \
else \
skipped="($$skip tests were not run)"; \
fi; \
test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
dashes="$$skipped"; \
fi; \
report=""; \
if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
report="Please report to $(PACKAGE_BUGREPORT)"; \
test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
dashes="$$report"; \
fi; \
dashes=`echo "$$dashes" | sed s/./=/g`; \
if test "$$failed" -eq 0; then \
col="$$grn"; \
else \
col="$$red"; \
fi; \
echo "$${col}$$dashes$${std}"; \
echo "$${col}$$banner$${std}"; \
test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
test -z "$$report" || echo "$${col}$$report$${std}"; \
echo "$${col}$$dashes$${std}"; \
test "$$failed" -eq 0; \
else :; fi
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
@ -1188,9 +1012,6 @@ install-strip:
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
-test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
-test -z "$(TEST_LOGS_TMP)" || rm -f $(TEST_LOGS_TMP)
-test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
@ -1258,8 +1079,8 @@ maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: am--mostlyclean-test-html mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
@ -1271,22 +1092,21 @@ ps-am:
uninstall-am:
.MAKE: check-am check-html install-am install-strip recheck-html
.MAKE: check-am install-am install-strip
.PHONY: CTAGS GTAGS all all-am am--mostlyclean-test-html check \
check-TESTS check-am check-html clean clean-checkPROGRAMS \
clean-generic clean-libtool clean-noinstPROGRAMS ctags \
distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-pdf install-pdf-am \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs maintainer-clean \
.PHONY: CTAGS GTAGS all all-am check check-TESTS check-am clean \
clean-checkPROGRAMS clean-generic clean-libtool \
clean-noinstPROGRAMS ctags distclean distclean-compile \
distclean-generic distclean-libtool distclean-tags distdir dvi \
dvi-am html html-am info info-am install install-am \
install-data install-data-am install-dvi install-dvi-am \
install-exec install-exec-am install-html install-html-am \
install-info install-info-am install-man install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
installcheck installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
recheck recheck-html tags uninstall uninstall-am
tags uninstall uninstall-am
$(builddir)/auto_check_header_%.c: $(top_srcdir)/include/qb/%.h

View File

@ -31,6 +31,7 @@
#include <signal.h>
#include <qb/qbdefs.h>
#include <qb/qbutil.h>
#include <qb/qbipcc.h>
#define ITERATIONS 10000000
@ -38,43 +39,31 @@
struct bm_ctx {
qb_ipcc_connection_t *conn;
struct timeval tv1;
struct timeval tv2;
struct timeval tv_elapsed;
qb_util_stopwatch_t *sw;
float mbs;
float secs;
int32_t multi;
uint32_t counter;
};
#define timersub(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)
static void bm_start(struct bm_ctx *ctx)
{
gettimeofday(&ctx->tv1, NULL);
qb_util_stopwatch_start(ctx->sw);
}
static void bm_finish(struct bm_ctx *ctx, const char *operation, int32_t size)
{
gettimeofday(&ctx->tv2, NULL);
timersub(&ctx->tv2, &ctx->tv1, &ctx->tv_elapsed);
qb_util_stopwatch_stop(ctx->sw);
ctx->secs = qb_util_stopwatch_sec_elapsed_get(ctx->sw);
ctx->mbs =
((((float)ctx->counter) * size) /
(((float)ctx->tv_elapsed.tv_sec) +
(((float)ctx->tv_elapsed.tv_usec) / 1000000.0))) / (1024.0 *
1024.0);
((((float)ctx->counter) * size) / ctx->secs) / (1024.0 *
1024.0);
}
static void bmc_connect(struct bm_ctx *ctx)
{
ctx->sw = qb_util_stopwatch_create();
ctx->conn = qb_ipcc_connect("bm1", QB_MAX(1000 * (100 + THREADS),
1024*1024));
if (ctx->conn == NULL) {
@ -86,6 +75,7 @@ static void bmc_connect(struct bm_ctx *ctx)
static void bmc_disconnect(struct bm_ctx *ctx)
{
qb_ipcc_disconnect(ctx->conn);
qb_util_stopwatch_free(ctx->sw);
}
struct my_req {

View File

@ -283,15 +283,9 @@ int32_t main(int32_t argc, char *argv[])
case 'm':
ipc_type = QB_IPC_SHM;
break;
case 's':
ipc_type = QB_IPC_SYSV_MQ;
break;
case 'u':
ipc_type = QB_IPC_SOCKET;
break;
case 'p':
ipc_type = QB_IPC_POSIX_MQ;
break;
case 'n': /* non-blocking */
blocking = QB_FALSE;
break;

View File

@ -21,12 +21,8 @@
* along with libqb. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include "os_base.h"
#include <sys/wait.h>
#include <errno.h>
#include <signal.h>
#include <check.h>
@ -46,8 +42,12 @@ enum my_msg_ids {
IPC_MSG_RES_TX_RX,
IPC_MSG_REQ_DISPATCH,
IPC_MSG_RES_DISPATCH,
IPC_MSG_REQ_BULK_EVENTS,
IPC_MSG_RES_BULK_EVENTS,
IPC_MSG_REQ_SERVER_FAIL,
IPC_MSG_RES_SERVER_FAIL,
IPC_MSG_REQ_SERVER_DISCONNECT,
IPC_MSG_RES_SERVER_DISCONNECT,
};
/* Test Cases
@ -72,6 +72,9 @@ static qb_loop_t *my_loop;
static qb_ipcs_service_t* s1;
static int32_t turn_on_fc = QB_FALSE;
static int32_t fc_enabled = 89;
static int32_t send_event_on_created = QB_FALSE;
static int32_t disconnect_after_created = QB_FALSE;
static int32_t num_bulk_events = 10;
static int32_t
exit_handler(int32_t rsignal, void *data)
@ -108,12 +111,40 @@ s1_msg_process_fn(qb_ipcs_connection_t *c,
response.id = IPC_MSG_RES_DISPATCH;
response.error = 0;
res = qb_ipcs_event_send(c, &response,
sizeof(response));
sizeof(response));
if (res < 0) {
qb_perror(LOG_INFO, "qb_ipcs_event_send");
}
} else if (req_pt->id == IPC_MSG_REQ_BULK_EVENTS) {
int32_t m;
int32_t num;
struct qb_ipcs_connection_stats_2 *stats;
response.size = sizeof(struct qb_ipc_response_header);
response.error = 0;
stats = qb_ipcs_connection_stats_get_2(c, QB_FALSE);
num = stats->event_q_length;
free(stats);
for (m = 0; m < num_bulk_events; m++) {
res = qb_ipcs_event_send(c, &response,
sizeof(response));
ck_assert_int_eq(res, sizeof(response));
response.id++;
}
stats = qb_ipcs_connection_stats_get_2(c, QB_FALSE);
ck_assert_int_eq(stats->event_q_length - num, num_bulk_events);
free(stats);
response.id = IPC_MSG_RES_BULK_EVENTS;
res = qb_ipcs_response_send(c, &response, response.size);
ck_assert_int_eq(res, sizeof(response));
} else if (req_pt->id == IPC_MSG_REQ_SERVER_FAIL) {
exit(0);
} else if (req_pt->id == IPC_MSG_REQ_SERVER_DISCONNECT) {
qb_ipcs_disconnect(c);
}
return 0;
}
@ -146,11 +177,36 @@ my_dispatch_del(int32_t fd)
return qb_loop_poll_del(my_loop, fd);
}
static int32_t
s1_connection_closed(qb_ipcs_connection_t *c)
{
qb_enter();
qb_leave();
return 0;
}
static void
s1_connection_destroyed(qb_ipcs_connection_t *c)
{
qb_enter();
qb_loop_stop(my_loop);
qb_leave();
}
static void
s1_connection_created(qb_ipcs_connection_t *c)
{
if (send_event_on_created) {
struct qb_ipc_response_header response;
int32_t res;
response.size = sizeof(struct qb_ipc_response_header);
response.id = IPC_MSG_RES_DISPATCH;
response.error = 0;
res = qb_ipcs_event_send(c, &response,
sizeof(response));
ck_assert_int_eq(res, response.size);
}
}
static void
@ -161,10 +217,10 @@ run_ipc_server(void)
struct qb_ipcs_service_handlers sh = {
.connection_accept = NULL,
.connection_created = NULL,
.connection_created = s1_connection_created,
.msg_process = s1_msg_process_fn,
.connection_destroyed = s1_connection_destroyed,
.connection_closed = NULL,
.connection_closed = s1_connection_closed,
};
struct qb_ipcs_poll_handlers ph = {
@ -226,13 +282,14 @@ struct my_req {
static struct my_req request;
static int32_t
send_and_check(uint32_t size, int32_t ms_timeout, int32_t expect_perfection)
send_and_check(int32_t req_id, uint32_t size,
int32_t ms_timeout, int32_t expect_perfection)
{
struct qb_ipc_response_header res_header;
int32_t res;
int32_t try_times = 0;
request.hdr.id = IPC_MSG_REQ_TX_RX;
request.hdr.id = req_id;
request.hdr.size = sizeof(struct qb_ipc_request_header) + size;
repeat_send:
@ -251,8 +308,16 @@ repeat_send:
return res;
}
}
res = qb_ipcc_recv(conn, &res_header,
sizeof(struct qb_ipc_response_header), ms_timeout);
if (req_id == IPC_MSG_REQ_DISPATCH) {
res = qb_ipcc_event_recv(conn, &res_header,
sizeof(struct qb_ipc_response_header),
ms_timeout);
} else {
res = qb_ipcc_recv(conn, &res_header,
sizeof(struct qb_ipc_response_header),
ms_timeout);
}
if (res == -EINTR) {
return -1;
}
@ -263,7 +328,7 @@ repeat_send:
}
if (expect_perfection) {
ck_assert_int_eq(res, sizeof(struct qb_ipc_response_header));
ck_assert_int_eq(res_header.id, IPC_MSG_RES_TX_RX);
ck_assert_int_eq(res_header.id, req_id + 1);
ck_assert_int_eq(res_header.size, sizeof(struct qb_ipc_response_header));
}
return res;
@ -298,7 +363,8 @@ test_ipc_txrx(void)
size *= 2;
if (size >= MAX_MSG_SIZE)
break;
if (send_and_check(size, recv_timeout, QB_TRUE) < 0) {
if (send_and_check(IPC_MSG_REQ_TX_RX, size,
recv_timeout, QB_TRUE) < 0) {
break;
}
}
@ -312,9 +378,12 @@ test_ipc_txrx(void)
static void
test_ipc_exit(void)
{
struct qb_ipc_request_header req_header;
struct qb_ipc_response_header res_header;
struct iovec iov[1];
int32_t res;
int32_t c = 0;
int32_t j = 0;
int32_t rc = 0;
pid_t pid;
pid = run_function_in_new_process(run_ipc_server);
@ -332,9 +401,16 @@ test_ipc_exit(void)
} while (conn == NULL && c < 5);
fail_if(conn == NULL);
/* confirm we can send one message */
rc = send_and_check(100, recv_timeout, QB_TRUE);
_ck_assert_int(rc, >=, 0);
req_header.id = IPC_MSG_REQ_TX_RX;
req_header.size = sizeof(struct qb_ipc_request_header);
iov[0].iov_len = req_header.size;
iov[0].iov_base = &req_header;
res = qb_ipcc_sendv_recv(conn, iov, 1,
&res_header,
sizeof(struct qb_ipc_response_header), -1);
ck_assert_int_eq(res, sizeof(struct qb_ipc_response_header));
/* kill the server */
stop_process(pid);
@ -350,91 +426,97 @@ test_ipc_exit(void)
qb_ipcc_disconnect(conn);
}
START_TEST(test_ipc_exit_us)
{
qb_enter();
ipc_type = QB_IPC_SOCKET;
ipc_name = __func__;
recv_timeout = 5000;
test_ipc_exit();
qb_leave();
}
END_TEST
START_TEST(test_ipc_exit_shm)
{
qb_enter();
ipc_type = QB_IPC_SHM;
ipc_name = __func__;
recv_timeout = 1000;
test_ipc_exit();
qb_leave();
}
END_TEST
START_TEST(test_ipc_txrx_shm_tmo)
{
qb_enter();
turn_on_fc = QB_FALSE;
ipc_type = QB_IPC_SHM;
ipc_name = __func__;
recv_timeout = 1000;
test_ipc_txrx();
qb_leave();
}
END_TEST
START_TEST(test_ipc_txrx_shm_block)
{
qb_enter();
turn_on_fc = QB_FALSE;
ipc_type = QB_IPC_SHM;
ipc_name = __func__;
recv_timeout = -1;
test_ipc_txrx();
}
END_TEST
START_TEST(test_ipc_txrx_us_block)
{
turn_on_fc = QB_FALSE;
ipc_type = QB_IPC_SOCKET;
ipc_name = __func__;
recv_timeout = -1;
test_ipc_txrx();
}
END_TEST
START_TEST(test_ipc_txrx_us_tmo)
{
turn_on_fc = QB_FALSE;
ipc_type = QB_IPC_SOCKET;
ipc_name = __func__;
recv_timeout = 1000;
test_ipc_txrx();
qb_leave();
}
END_TEST
START_TEST(test_ipc_fc_shm)
{
qb_enter();
turn_on_fc = QB_TRUE;
ipc_type = QB_IPC_SHM;
recv_timeout = 500;
ipc_name = __func__;
test_ipc_txrx();
qb_leave();
}
END_TEST
START_TEST(test_ipc_txrx_us_block)
{
qb_enter();
turn_on_fc = QB_FALSE;
ipc_type = QB_IPC_SOCKET;
ipc_name = __func__;
recv_timeout = -1;
test_ipc_txrx();
qb_leave();
}
END_TEST
START_TEST(test_ipc_txrx_us_tmo)
{
qb_enter();
turn_on_fc = QB_FALSE;
ipc_type = QB_IPC_SOCKET;
ipc_name = __func__;
recv_timeout = 1000;
test_ipc_txrx();
qb_leave();
}
END_TEST
START_TEST(test_ipc_fc_us)
{
qb_enter();
turn_on_fc = QB_TRUE;
ipc_type = QB_IPC_SOCKET;
recv_timeout = 500;
ipc_name = __func__;
test_ipc_txrx();
}
END_TEST
START_TEST(test_ipc_txrx_pmq)
{
turn_on_fc = QB_FALSE;
ipc_type = QB_IPC_POSIX_MQ;
ipc_name = __func__;
test_ipc_txrx();
}
END_TEST
START_TEST(test_ipc_txrx_smq)
{
turn_on_fc = QB_FALSE;
ipc_type = QB_IPC_SYSV_MQ;
ipc_name = __func__;
test_ipc_txrx();
qb_leave();
}
END_TEST
@ -443,15 +525,13 @@ struct my_res {
char message[1024 * 1024];
};
static struct my_res response;
static void
test_ipc_dispatch(void)
{
int32_t res;
int32_t j;
int32_t c = 0;
pid_t pid;
struct qb_ipc_request_header req_header;
int32_t size;
pid = run_function_in_new_process(run_ipc_server);
fail_if(pid == -1);
@ -468,54 +548,230 @@ test_ipc_dispatch(void)
} while (conn == NULL && c < 5);
fail_if(conn == NULL);
req_header.id = IPC_MSG_REQ_DISPATCH;
req_header.size = sizeof(struct qb_ipc_request_header);
repeat_send:
res = qb_ipcc_send(conn, &req_header, req_header.size);
if (res < 0) {
if (res == -EAGAIN) {
goto repeat_send;
} else if (res == -EINVAL || res == -EINTR) {
qb_perror(LOG_INFO, "qb_ipcc_send");
return;
} else {
errno = -res;
qb_perror(LOG_INFO, "qb_ipcc_send");
goto repeat_send;
size = QB_MIN(sizeof(struct qb_ipc_request_header), 64);
for (j = 1; j < 19; j++) {
size *= 2;
if (size >= MAX_MSG_SIZE)
break;
if (send_and_check(IPC_MSG_REQ_DISPATCH, size,
recv_timeout, QB_TRUE) < 0) {
break;
}
}
repeat_event_recv:
res = qb_ipcc_event_recv(conn, &response, sizeof(struct my_res), 0);
if (res < 0) {
if (res == -EAGAIN || res == -ETIMEDOUT) {
goto repeat_event_recv;
} else {
errno = -res;
qb_perror(LOG_INFO, "qb_ipcc_event_recv");
goto repeat_send;
}
}
ck_assert_int_eq(res, sizeof(struct qb_ipc_response_header));
ck_assert_int_eq(response.hdr.id, IPC_MSG_RES_DISPATCH);
qb_ipcc_disconnect(conn);
stop_process(pid);
}
START_TEST(test_ipc_disp_shm)
{
ipc_type = QB_IPC_SHM;
ipc_name = __func__;
test_ipc_dispatch();
}
END_TEST
START_TEST(test_ipc_disp_us)
{
qb_enter();
ipc_type = QB_IPC_SOCKET;
ipc_name = __func__;
test_ipc_dispatch();
qb_leave();
}
END_TEST
static int32_t events_received;
static int32_t
count_bulk_events(int32_t fd, int32_t revents, void *data)
{
qb_loop_t *cl = (qb_loop_t*)data;
events_received++;
if (events_received >= num_bulk_events) {
qb_loop_stop(cl);
return -1;
}
return 0;
}
static void
test_ipc_bulk_events(void)
{
struct qb_ipc_request_header req_header;
struct qb_ipc_response_header res_header;
struct iovec iov[1];
int32_t c = 0;
int32_t j = 0;
pid_t pid;
int32_t res;
qb_loop_t *cl;
int32_t fd;
pid = run_function_in_new_process(run_ipc_server);
fail_if(pid == -1);
sleep(1);
do {
conn = qb_ipcc_connect(ipc_name, MAX_MSG_SIZE);
if (conn == NULL) {
j = waitpid(pid, NULL, WNOHANG);
ck_assert_int_eq(j, 0);
sleep(1);
c++;
}
} while (conn == NULL && c < 5);
fail_if(conn == NULL);
events_received = 0;
cl = qb_loop_create();
res = qb_ipcc_fd_get(conn, &fd),
ck_assert_int_eq(res, 0);
res = qb_loop_poll_add(cl, QB_LOOP_MED,
fd, POLLIN,
cl, count_bulk_events);
ck_assert_int_eq(res, 0);
res = send_and_check(IPC_MSG_REQ_BULK_EVENTS,
0,
recv_timeout, QB_TRUE);
ck_assert_int_eq(res, sizeof(struct qb_ipc_response_header));
qb_loop_run(cl);
ck_assert_int_eq(events_received, num_bulk_events);
req_header.id = IPC_MSG_REQ_SERVER_FAIL;
req_header.size = sizeof(struct qb_ipc_request_header);
iov[0].iov_len = req_header.size;
iov[0].iov_base = &req_header;
res = qb_ipcc_sendv_recv(conn, iov, 1,
&res_header,
sizeof(struct qb_ipc_response_header), -1);
if (res != -ECONNRESET && res != -ENOTCONN) {
qb_log(LOG_ERR, "id:%d size:%d", res_header.id, res_header.size);
ck_assert_int_eq(res, -ENOTCONN);
}
qb_ipcc_disconnect(conn);
stop_process(pid);
}
START_TEST(test_ipc_bulk_events_us)
{
qb_enter();
send_event_on_created = QB_FALSE;
ipc_type = QB_IPC_SOCKET;
ipc_name = __func__;
test_ipc_bulk_events();
qb_leave();
}
END_TEST
static void
test_ipc_event_on_created(void)
{
int32_t c = 0;
int32_t j = 0;
pid_t pid;
int32_t res;
qb_loop_t *cl;
int32_t fd;
num_bulk_events = 1;
pid = run_function_in_new_process(run_ipc_server);
fail_if(pid == -1);
sleep(1);
do {
conn = qb_ipcc_connect(ipc_name, MAX_MSG_SIZE);
if (conn == NULL) {
j = waitpid(pid, NULL, WNOHANG);
ck_assert_int_eq(j, 0);
sleep(1);
c++;
}
} while (conn == NULL && c < 5);
fail_if(conn == NULL);
events_received = 0;
cl = qb_loop_create();
res = qb_ipcc_fd_get(conn, &fd),
ck_assert_int_eq(res, 0);
res = qb_loop_poll_add(cl, QB_LOOP_MED,
fd, POLLIN,
cl, count_bulk_events);
ck_assert_int_eq(res, 0);
qb_loop_run(cl);
ck_assert_int_eq(events_received, num_bulk_events);
qb_ipcc_disconnect(conn);
stop_process(pid);
}
START_TEST(test_ipc_event_on_created_us)
{
qb_enter();
send_event_on_created = QB_TRUE;
ipc_type = QB_IPC_SOCKET;
ipc_name = __func__;
test_ipc_event_on_created();
qb_leave();
}
END_TEST
static void
test_ipc_disconnect_after_created(void)
{
struct qb_ipc_request_header req_header;
struct qb_ipc_response_header res_header;
struct iovec iov[1];
int32_t c = 0;
int32_t j = 0;
pid_t pid;
int32_t res;
pid = run_function_in_new_process(run_ipc_server);
fail_if(pid == -1);
sleep(1);
do {
conn = qb_ipcc_connect(ipc_name, MAX_MSG_SIZE);
if (conn == NULL) {
j = waitpid(pid, NULL, WNOHANG);
ck_assert_int_eq(j, 0);
sleep(1);
c++;
}
} while (conn == NULL && c < 5);
fail_if(conn == NULL);
ck_assert_int_eq(QB_TRUE, qb_ipcc_is_connected(conn));
req_header.id = IPC_MSG_REQ_SERVER_DISCONNECT;
req_header.size = sizeof(struct qb_ipc_request_header);
iov[0].iov_len = req_header.size;
iov[0].iov_base = &req_header;
res = qb_ipcc_sendv_recv(conn, iov, 1,
&res_header,
sizeof(struct qb_ipc_response_header), -1);
/*
* confirm we get -ENOTCONN
*/
ck_assert_int_eq(res, -ENOTCONN);
ck_assert_int_eq(QB_FALSE, qb_ipcc_is_connected(conn));
qb_ipcc_disconnect(conn);
stop_process(pid);
}
START_TEST(test_ipc_disconnect_after_created_us)
{
qb_enter();
disconnect_after_created = QB_TRUE;
ipc_type = QB_IPC_SOCKET;
ipc_name = __func__;
test_ipc_disconnect_after_created();
qb_leave();
}
END_TEST
@ -554,6 +810,8 @@ test_ipc_server_fail(void)
iov[0].iov_len = req_header.size;
iov[0].iov_base = &req_header;
ck_assert_int_eq(QB_TRUE, qb_ipcc_is_connected(conn));
res = qb_ipcc_sendv_recv(conn, iov, 1,
&res_header,
sizeof(struct qb_ipc_response_header), -1);
@ -561,6 +819,7 @@ test_ipc_server_fail(void)
* confirm we get -ENOTCONN
*/
ck_assert_int_eq(res, -ENOTCONN);
ck_assert_int_eq(QB_FALSE, qb_ipcc_is_connected(conn));
qb_ipcc_disconnect(conn);
stop_process(pid);
@ -568,37 +827,67 @@ test_ipc_server_fail(void)
START_TEST(test_ipc_server_fail_soc)
{
qb_enter();
ipc_type = QB_IPC_SOCKET;
ipc_name = __func__;
test_ipc_server_fail();
qb_leave();
}
END_TEST
START_TEST(test_ipc_disp_shm)
{
qb_enter();
ipc_type = QB_IPC_SHM;
ipc_name = __func__;
test_ipc_dispatch();
qb_leave();
}
END_TEST
START_TEST(test_ipc_bulk_events_shm)
{
qb_enter();
ipc_type = QB_IPC_SHM;
ipc_name = __func__;
test_ipc_bulk_events();
qb_leave();
}
END_TEST
START_TEST(test_ipc_event_on_created_shm)
{
qb_enter();
send_event_on_created = QB_TRUE;
ipc_type = QB_IPC_SHM;
ipc_name = __func__;
test_ipc_event_on_created();
qb_leave();
}
END_TEST
START_TEST(test_ipc_server_fail_shm)
{
qb_enter();
ipc_type = QB_IPC_SHM;
ipc_name = __func__;
test_ipc_server_fail();
qb_leave();
}
END_TEST
static Suite *
ipc_suite(void)
make_shm_suite(void)
{
TCase *tc;
uid_t uid;
Suite *s = suite_create("ipc");
Suite *s = suite_create("shm");
tc = tcase_create("ipc_server_fail_shm");
tcase_add_test(tc, test_ipc_server_fail_shm);
tcase_set_timeout(tc, 6);
suite_add_tcase(s, tc);
tc = tcase_create("ipc_server_fail_soc");
tcase_add_test(tc, test_ipc_server_fail_soc);
tcase_set_timeout(tc, 6);
suite_add_tcase(s, tc);
tc = tcase_create("ipc_txrx_shm_block");
tcase_add_test(tc, test_ipc_txrx_shm_block);
tcase_set_timeout(tc, 6);
@ -609,6 +898,44 @@ ipc_suite(void)
tcase_set_timeout(tc, 6);
suite_add_tcase(s, tc);
tc = tcase_create("ipc_fc_shm");
tcase_add_test(tc, test_ipc_fc_shm);
tcase_set_timeout(tc, 6);
suite_add_tcase(s, tc);
tc = tcase_create("ipc_dispatch_shm");
tcase_add_test(tc, test_ipc_disp_shm);
tcase_set_timeout(tc, 16);
suite_add_tcase(s, tc);
tc = tcase_create("ipc_bulk_events_shm");
tcase_add_test(tc, test_ipc_bulk_events_shm);
tcase_set_timeout(tc, 16);
suite_add_tcase(s, tc);
tc = tcase_create("ipc_exit_shm");
tcase_add_test(tc, test_ipc_exit_shm);
tcase_set_timeout(tc, 3);
suite_add_tcase(s, tc);
tc = tcase_create("ipc_event_on_created_shm");
tcase_add_test(tc, test_ipc_event_on_created_shm);
suite_add_tcase(s, tc);
return s;
}
static Suite *
make_soc_suite(void)
{
Suite *s = suite_create("socket");
TCase *tc;
tc = tcase_create("ipc_server_fail_soc");
tcase_add_test(tc, test_ipc_server_fail_soc);
tcase_set_timeout(tc, 6);
suite_add_tcase(s, tc);
tc = tcase_create("ipc_txrx_us_block");
tcase_add_test(tc, test_ipc_txrx_us_block);
tcase_set_timeout(tc, 6);
@ -619,31 +946,14 @@ ipc_suite(void)
tcase_set_timeout(tc, 6);
suite_add_tcase(s, tc);
tc = tcase_create("ipc_fc_shm");
tcase_add_test(tc, test_ipc_fc_shm);
tcase_set_timeout(tc, 6);
suite_add_tcase(s, tc);
tc = tcase_create("ipc_fc_us");
tcase_add_test(tc, test_ipc_fc_us);
tcase_set_timeout(tc, 6);
suite_add_tcase(s, tc);
uid = geteuid();
if (uid == 0) {
tc = tcase_create("ipc_txrx_posix_mq");
tcase_add_test(tc, test_ipc_txrx_pmq);
tcase_set_timeout(tc, 10);
suite_add_tcase(s, tc);
tc = tcase_create("ipc_txrx_sysv_mq");
tcase_add_test(tc, test_ipc_txrx_smq);
tcase_set_timeout(tc, 10);
suite_add_tcase(s, tc);
}
tc = tcase_create("ipc_dispatch_shm");
tcase_add_test(tc, test_ipc_disp_shm);
tcase_set_timeout(tc, 16);
tc = tcase_create("ipc_exit_us");
tcase_add_test(tc, test_ipc_exit_us);
tcase_set_timeout(tc, 6);
suite_add_tcase(s, tc);
tc = tcase_create("ipc_dispatch_us");
@ -651,9 +961,17 @@ ipc_suite(void)
tcase_set_timeout(tc, 16);
suite_add_tcase(s, tc);
tc = tcase_create("ipc_exit_shm");
tcase_add_test(tc, test_ipc_exit_shm);
tcase_set_timeout(tc, 3);
tc = tcase_create("ipc_bulk_events_us");
tcase_add_test(tc, test_ipc_bulk_events_us);
tcase_set_timeout(tc, 16);
suite_add_tcase(s, tc);
tc = tcase_create("ipc_event_on_created_us");
tcase_add_test(tc, test_ipc_event_on_created_us);
suite_add_tcase(s, tc);
tc = tcase_create("ipc_disconnect_after_created_us");
tcase_add_test(tc, test_ipc_disconnect_after_created_us);
suite_add_tcase(s, tc);
return s;
@ -663,15 +981,27 @@ int32_t
main(void)
{
int32_t number_failed;
SRunner *sr;
Suite *s;
int32_t do_shm_tests = QB_TRUE;
Suite *s = ipc_suite();
SRunner *sr = srunner_create(s);
#ifdef DISABLE_IPC_SHM
do_shm_tests = QB_FALSE;
#endif /* DISABLE_IPC_SHM */
s = make_soc_suite();
sr = srunner_create(s);
if (do_shm_tests) {
srunner_add_suite(sr, make_shm_suite());
}
qb_log_init("check", LOG_USER, LOG_EMERG);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "*", LOG_INFO);
QB_LOG_FILTER_FILE, "*", LOG_TRACE);
qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
qb_log_format_set(QB_LOG_STDERR, "lib/%f|%l| %b");
srunner_run_all(sr, CK_VERBOSE);
number_failed = srunner_ntests_failed(sr);

View File

@ -29,7 +29,7 @@
#include <qb/qbutil.h>
#include <qb/qblog.h>
extern size_t qb_vsprintf_serialize(char *serialize, const char *fmt, va_list ap);
extern size_t qb_vsnprintf_serialize(char *serialize, size_t max_len, const char *fmt, va_list ap);
extern size_t qb_vsnprintf_deserialize(char *string, size_t strlen, const char *buf);
@ -40,18 +40,35 @@ format_this(char *out, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
qb_vsprintf_serialize(buf, fmt, ap);
qb_vsnprintf_serialize(buf, QB_LOG_MAX_LEN, fmt, ap);
qb_vsnprintf_deserialize(out, QB_LOG_MAX_LEN, buf);
va_end(ap);
}
static void
format_this_up_to(char *out, size_t max_len, const char *fmt, ...)
{
char buf[QB_LOG_MAX_LEN];
va_list ap;
va_start(ap, fmt);
qb_vsnprintf_serialize(buf, max_len, fmt, ap);
qb_vsnprintf_deserialize(out, QB_LOG_MAX_LEN, buf);
va_end(ap);
}
START_TEST(test_va_serialize)
{
char buf[QB_LOG_MAX_LEN];
char cmp_buf[QB_LOG_MAX_LEN];
format_this(buf, "one line");
ck_assert_str_eq(buf, "one line");
format_this(buf, "p1:%p, p2:%p", format_this, buf);
snprintf(cmp_buf, QB_LOG_MAX_LEN, "p1:%p, p2:%p", format_this, buf);
ck_assert_str_eq(buf, cmp_buf);
format_this(buf, "s1:%s, s2:%s", "Yes", "Never");
ck_assert_str_eq(buf, "s1:Yes, s2:Never");
@ -83,6 +100,9 @@ START_TEST(test_va_serialize)
format_this(buf, ":%*d:", 8, 96);
ck_assert_str_eq(buf, ": 96:");
format_this_up_to(buf, 11, "123456789____");
ck_assert_str_eq(buf, "123456789_");
}
END_TEST
@ -553,16 +573,80 @@ END_TEST
START_TEST(test_log_long_msg)
{
qb_log_init("test", LOG_USER, LOG_DEBUG);
qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
qb_log_format_set(QB_LOG_SYSLOG, "%b");
int lpc;
int rc;
int i, max = 1000;
char *buffer = calloc(1, max);
qb_log(LOG_ERR, "QMF Agent Initialized: broker=localhost:49000 interval=5 storeFile=.cloudpolicyengine-data-cpe name=cloudpolicyengine.org:cpe:04eabb39-89cf-47dd-9d14-7e77d864be07 QMF Agent Initialized: broker=localhost:49000 interval=5 storeFile=.cloudpolicyengine-data-cpe name=cloudpolicyengine.org:cpe:04eabb39-89cf-47dd-9d14-7e77d864be07 QMF Agent Initialized: broker=localhost:49000 interval=5 storeFile=.cloudpolicyengine-data-cpe name=cloudpolicyengine.org:cpe:04eabb39-89cf-47dd-9d14-7e77d864be07");
qb_log_init("test", LOG_USER, LOG_DEBUG);
rc = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
ck_assert_int_eq(rc, 0);
rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 1024);
ck_assert_int_eq(rc, 0);
rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
ck_assert_int_eq(rc, 0);
rc = qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "*", LOG_TRACE);
ck_assert_int_eq(rc, 0);
for (lpc = 500; lpc < max; lpc++) {
lpc++;
for(i = 0; i < max; i++) {
buffer[i] = 'a' + (i % 10);
}
buffer[lpc%600] = 0;
qb_log(LOG_INFO, "Message %d %d - %s", lpc, lpc%600, buffer);
}
qb_log_blackbox_write_to_file("blackbox.dump");
qb_log_blackbox_print_from_file("blackbox.dump");
unlink("blackbox.dump");
qb_log_fini();
}
END_TEST
static Suite *log_suite(void)
START_TEST(test_threaded_logging)
{
int32_t t;
int32_t rc;
qb_log_init("test", LOG_USER, LOG_EMERG);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
rc = qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "*", LOG_INFO);
ck_assert_int_eq(rc, 0);
qb_log_format_set(t, "%b");
rc = qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
ck_assert_int_eq(rc, 0);
rc = qb_log_ctl(t, QB_LOG_CONF_THREADED, QB_TRUE);
ck_assert_int_eq(rc, 0);
qb_log_thread_start();
memset(test_buf, 0, sizeof(test_buf));
test_priority = 0;
num_msgs = 0;
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log_fini();
ck_assert_int_eq(num_msgs, 10);
}
END_TEST
static Suite *
log_suite(void)
{
TCase *tc;
Suite *s = suite_create("logging");
@ -600,6 +684,10 @@ static Suite *log_suite(void)
tcase_add_test(tc, test_log_filter_fn);
suite_add_tcase(s, tc);
tc = tcase_create("threaded_logging");
tcase_add_test(tc, test_threaded_logging);
suite_add_tcase(s, tc);
return s;
}

View File

@ -105,10 +105,6 @@ START_TEST(test_ring_buffer2)
}
for (i = 0; i < 100; i++) {
l = qb_rb_chunk_peek(t, (void **)&new_data, 0);
if (l < 0) {
/* no more to read */
break;
}
ck_assert_int_eq(l, sizeof(v));
fail_unless(v == *new_data);
qb_rb_chunk_reclaim(t);

View File

@ -28,9 +28,10 @@
#include <qb/qbutil.h>
#include <qb/qblog.h>
#define BUFFER_CHUNK_SIZE (50*50*10)
#define ONE_MEG 1048576
static qb_ringbuffer_t *rb = NULL;
static int keep_reading = QB_TRUE;
int8_t buffer[ONE_MEG];
static void sigterm_handler(int32_t num)
@ -42,18 +43,18 @@ static void sigterm_handler(int32_t num)
int32_t main(int32_t argc, char *argv[])
{
ssize_t num_read;
int8_t buffer[BUFFER_CHUNK_SIZE];
signal(SIGINT, sigterm_handler);
qb_log_init("rbreader", LOG_USER, LOG_EMERG);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "*", LOG_INFO);
QB_LOG_FILTER_FILE, "*", LOG_TRACE);
qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
rb = qb_rb_open("tester", BUFFER_CHUNK_SIZE * 3,
QB_RB_FLAG_SHARED_PROCESS | QB_RB_FLAG_CREATE, 0);
rb = qb_rb_open("tester", ONE_MEG * 3,
QB_RB_FLAG_SHARED_PROCESS |
QB_RB_FLAG_CREATE, 0);
if (rb == NULL) {
qb_perror(LOG_ERR, "failed to create ringbuffer");
@ -61,8 +62,11 @@ int32_t main(int32_t argc, char *argv[])
}
while (keep_reading) {
num_read = qb_rb_chunk_read(rb, buffer,
BUFFER_CHUNK_SIZE, 5500);
if (num_read < 0) {
ONE_MEG, 0);
if (num_read == -ETIMEDOUT) {
usleep(100000);
} else if (num_read < 0) {
errno = -num_read;
qb_perror(LOG_ERR, "nothing to read");
}
}

View File

@ -35,21 +35,16 @@
#include <qb/qbutil.h>
#include <qb/qblog.h>
static int alarm_notice = 0;
static qb_ringbuffer_t *rb = NULL;
#define ITERATIONS 100000
#define BUFFER_CHUNK_SIZE (50*50*10)
static qb_util_stopwatch_t *sw;
#define ONE_MEG 1048576
static char buffer[ONE_MEG * 3];
static struct timeval tv1, tv2, tv_elapsed;
#define timersub(a, b, result) \
do { \
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
if ((result)->tv_usec < 0) { \
--(result)->tv_sec; \
(result)->tv_usec += 1000000; \
} \
} while (0)
static void sigalrm_handler (int num)
{
alarm_notice = 1;
}
static void sigterm_handler(int32_t num)
{
@ -58,53 +53,56 @@ static void sigterm_handler(int32_t num)
exit(0);
}
static void bm_start(void)
static void
_benchmark(ssize_t write_size)
{
gettimeofday(&tv1, NULL);
}
ssize_t res;
int write_count = 0;
float secs;
static void bm_finish(const char *operation, int32_t size)
{
float ops_per_sec;
float mbs_per_sec;
alarm_notice = 0;
gettimeofday(&tv2, NULL);
timersub(&tv2, &tv1, &tv_elapsed);
alarm (10);
ops_per_sec =
((float)ITERATIONS) / (((float)tv_elapsed.tv_sec) +
(((float)tv_elapsed.tv_usec) / 1000000.0));
mbs_per_sec =
((((float)ITERATIONS) * size) /
(((float)tv_elapsed.tv_sec) +
(((float)tv_elapsed.tv_usec) / 1000000.0))) / (1024.0 * 1024.0);
qb_log(LOG_INFO, "write size %d OPs/sec %9.3f MB/sec %9.3f",
size, ops_per_sec, mbs_per_sec);
}
static void bmc_connect(void)
{
rb = qb_rb_open("tester", BUFFER_CHUNK_SIZE * 3,
QB_RB_FLAG_SHARED_PROCESS, 0);
if (rb == NULL) {
qb_perror(LOG_ERR, "failed to create ringbuffer");
exit(1);
qb_util_stopwatch_start(sw);
do {
res = qb_rb_chunk_write(rb, buffer, write_size);
if (res == write_size) {
write_count++;
}
} while (alarm_notice == 0 && (res == write_size || res == -EAGAIN));
if (res < 0) {
perror("qb_ipcc_sendv");
}
qb_util_stopwatch_stop(sw);
secs = qb_util_stopwatch_sec_elapsed_get(sw);
printf ("%5d messages sent ", write_count);
printf ("%5ld bytes per write ", (long int) write_size);
printf ("%7.3f Seconds runtime ", secs);
printf ("%9.3f TP/s ",
((float)write_count) / secs);
printf ("%7.3f MB/s.\n",
((float)write_count) * ((float)write_size) / secs);
}
static char buffer[1024 * 1024];
static void bmc_send_nozc(size_t size)
{
ssize_t res = 0;
repeat_send:
res = qb_rb_chunk_write(rb, buffer, size);
if (res < size) {
goto repeat_send;
static void
do_throughput_benchmark(void)
{
ssize_t size = 64;
int i;
signal (SIGALRM, sigalrm_handler);
sw = qb_util_stopwatch_create();
for (i = 0; i < 10; i++) { /* number of repetitions - up to 50k */
_benchmark(size);
signal (SIGALRM, sigalrm_handler);
size *= 5;
if (size >= ONE_MEG) {
break;
}
}
}
@ -125,8 +123,6 @@ int32_t main(int32_t argc, char *argv[])
{
const char *options = "vh";
int32_t opt;
int32_t i, j;
int32_t size;
int32_t verbose = 0;
while ((opt = getopt(argc, argv, options)) != -1) {
@ -150,21 +146,9 @@ int32_t main(int32_t argc, char *argv[])
QB_LOG_FILTER_FILE, "*", LOG_INFO + verbose);
qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
bmc_connect();
for (j = 1; j < 49; j++) {
bm_start();
size = 7 * (j + 1) * j;
if (size > BUFFER_CHUNK_SIZE) {
size = BUFFER_CHUNK_SIZE;
}
for (i = 0; i < ITERATIONS; i++) {
bmc_send_nozc(size);
}
bm_finish("ringbuffer", size);
}
rb = qb_rb_open("tester", ONE_MEG * 3,
QB_RB_FLAG_SHARED_PROCESS, 0);
do_throughput_benchmark();
qb_rb_close(rb);
return EXIT_SUCCESS;
}

View File

@ -1,13 +1,17 @@
#!/bin/bash
#!/bin/sh
RETURN=0
ls /dev/shm/qb-test* 2>/dev/null
if [ $? -eq 0 ]
then
echo
echo "Error: shared memory segments not closed/unlinked"
echo
RETURN=1
fi
for d in /dev/shm /var/run
do
ls $d/qb-test* 2>/dev/null
if [ $? -eq 0 ]
then
echo
echo "Error: shared memory segments not closed/unlinked"
echo
RETURN=1
fi
done
ps aux | grep -v grep | grep lt-check
if [ $? -eq 0 ]
then
@ -16,4 +20,3 @@ then
fi
exit $RETURN

28
tools/Makefile.am Normal file
View File

@ -0,0 +1,28 @@
# Copyright (c) 2011 Red Hat, Inc.
#
# Authors: Angus Salkeld <asalkeld@redhat.com>
#
# This file is part of libqb.
#
# libqb 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.
#
# libqb 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 libqb. If not, see <http://www.gnu.org/licenses/>.
#
MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST =
CLEANFILES =
sbin_PROGRAMS = qb-blackbox
qb_blackbox_SOURCES = qb_blackbox.c $(top_builddir)/include/qb/qblog.h
qb_blackbox_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
qb_blackbox_LDADD = $(top_builddir)/lib/libqb.la

590
tools/Makefile.in Normal file
View File

@ -0,0 +1,590 @@
# Makefile.in generated by automake 1.11.3 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
# Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
sbin_PROGRAMS = qb-blackbox$(EXEEXT)
subdir = tools
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h \
$(top_builddir)/include/qb/qbconfig.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(sbindir)"
PROGRAMS = $(sbin_PROGRAMS)
am_qb_blackbox_OBJECTS = qb_blackbox-qb_blackbox.$(OBJEXT)
qb_blackbox_OBJECTS = $(am_qb_blackbox_OBJECTS)
qb_blackbox_DEPENDENCIES = $(top_builddir)/lib/libqb.la
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include -I$(top_builddir)/include/qb
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
SOURCES = $(qb_blackbox_SOURCES)
DIST_SOURCES = $(qb_blackbox_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CHECK_CFLAGS = @CHECK_CFLAGS@
CHECK_LIBS = @CHECK_LIBS@
CP = @CP@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GLIB_CFLAGS = @GLIB_CFLAGS@
GLIB_LIBS = @GLIB_LIBS@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LINT_FLAGS = @LINT_FLAGS@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKGCONFIG = @PKGCONFIG@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
SOCKETDIR = @SOCKETDIR@
SPLINT = @SPLINT@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
# Copyright (c) 2011 Red Hat, Inc.
#
# Authors: Angus Salkeld <asalkeld@redhat.com>
#
# This file is part of libqb.
#
# libqb 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.
#
# libqb 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 libqb. If not, see <http://www.gnu.org/licenses/>.
#
MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST =
CLEANFILES =
qb_blackbox_SOURCES = qb_blackbox.c $(top_builddir)/include/qb/qblog.h
qb_blackbox_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
qb_blackbox_LDADD = $(top_builddir)/lib/libqb.la
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tools/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu tools/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
install-sbinPROGRAMS: $(sbin_PROGRAMS)
@$(NORMAL_INSTALL)
test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p || test -f $$p1; \
then echo "$$p"; echo "$$p"; else :; fi; \
done | \
sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
if ($$2 == $$4) files[d] = files[d] " " $$1; \
else { print "f", $$3 "/" $$4, $$1; } } \
END { for (d in files) print "f", d, files[d] }' | \
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \
$(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \
} \
; done
uninstall-sbinPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-e 's/$$/$(EXEEXT)/' `; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(sbindir)" && rm -f $$files
clean-sbinPROGRAMS:
@list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \
echo " rm -f" $$list; \
rm -f $$list || exit $$?; \
test -n "$(EXEEXT)" || exit 0; \
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
qb-blackbox$(EXEEXT): $(qb_blackbox_OBJECTS) $(qb_blackbox_DEPENDENCIES) $(EXTRA_qb_blackbox_DEPENDENCIES)
@rm -f qb-blackbox$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(qb_blackbox_OBJECTS) $(qb_blackbox_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qb_blackbox-qb_blackbox.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
qb_blackbox-qb_blackbox.o: qb_blackbox.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(qb_blackbox_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT qb_blackbox-qb_blackbox.o -MD -MP -MF $(DEPDIR)/qb_blackbox-qb_blackbox.Tpo -c -o qb_blackbox-qb_blackbox.o `test -f 'qb_blackbox.c' || echo '$(srcdir)/'`qb_blackbox.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/qb_blackbox-qb_blackbox.Tpo $(DEPDIR)/qb_blackbox-qb_blackbox.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='qb_blackbox.c' object='qb_blackbox-qb_blackbox.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(qb_blackbox_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o qb_blackbox-qb_blackbox.o `test -f 'qb_blackbox.c' || echo '$(srcdir)/'`qb_blackbox.c
qb_blackbox-qb_blackbox.obj: qb_blackbox.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(qb_blackbox_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT qb_blackbox-qb_blackbox.obj -MD -MP -MF $(DEPDIR)/qb_blackbox-qb_blackbox.Tpo -c -o qb_blackbox-qb_blackbox.obj `if test -f 'qb_blackbox.c'; then $(CYGPATH_W) 'qb_blackbox.c'; else $(CYGPATH_W) '$(srcdir)/qb_blackbox.c'; fi`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/qb_blackbox-qb_blackbox.Tpo $(DEPDIR)/qb_blackbox-qb_blackbox.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='qb_blackbox.c' object='qb_blackbox-qb_blackbox.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(qb_blackbox_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o qb_blackbox-qb_blackbox.obj `if test -f 'qb_blackbox.c'; then $(CYGPATH_W) 'qb_blackbox.c'; else $(CYGPATH_W) '$(srcdir)/qb_blackbox.c'; fi`
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(PROGRAMS)
installdirs:
for dir in "$(DESTDIR)$(sbindir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
clean: clean-am
clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \
mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am: install-sbinPROGRAMS
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-sbinPROGRAMS
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-libtool clean-sbinPROGRAMS ctags distclean \
distclean-compile distclean-generic distclean-libtool \
distclean-tags distdir dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-sbinPROGRAMS install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags uninstall uninstall-am uninstall-sbinPROGRAMS
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

34
tools/qb_blackbox.c Normal file
View File

@ -0,0 +1,34 @@
/*
* Copyright (C) 2012 Andrew Beekhof <andrew@beekhof.net>
*
* libqb 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.
*
* libqb 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 libqb. If not, see <http://www.gnu.org/licenses/>.
*/
#include <qb/qblog.h>
int
main(int argc, char **argv)
{
int lpc = 0;
qb_log_init("qb_blackbox", LOG_USER, LOG_TRACE);
qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FILE, "*", LOG_TRACE);
for(lpc = 1; lpc < argc && argv[lpc] != NULL; lpc++) {
printf("Dumping the contents of %s\n", argv[lpc]);
qb_log_blackbox_print_from_file(argv[lpc]);
}
return 0;
}