diff --git a/docs/Makefile.am b/docs/Makefile.am index f4b6197..0c6eaa3 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -1,48 +1,48 @@ # Copyright (C) 2010 Red Hat, Inc. # # Authors: Angus Salkeld # # 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 . MAINTAINERCLEANFILES = Makefile.in EXTRA_DIST = man.dox html.dox noinst_HEADERS = mainpage.h dist_man_MANS = man8/qb-blackbox.8 if HAVE_DOXYGEN inc_dir = $(top_srcdir)/include/qb 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 $(dist_man_MANS): man.dox $(dependant_headers) - @mkdir -p man3 - @doxygen man.dox + mkdir -p man3 + doxygen man.dox doxygen: html.dox - @mkdir -p html - @doxygen html.dox + mkdir -p html + doxygen html.dox else doxygen: @echo WARNING: no doxygen to build man pages! endif clean-generic: rm -rf html man3 diff --git a/docs/html.dox.in b/docs/html.dox.in index abeef17..b477972 100644 --- a/docs/html.dox.in +++ b/docs/html.dox.in @@ -1,213 +1,210 @@ DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = libqb PROJECT_NUMBER = @VERSION@ OUTPUT_DIRECTORY = . CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = YES ALWAYS_DETAILED_SEC = YES INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = NO STRIP_FROM_PATH = STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = YES QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 8 ALIASES = OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO EXTENSION_MAPPING = BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO SIP_SUPPORT = NO IDL_PROPERTY_SUPPORT = NO DISTRIBUTE_GROUP_DOC = YES SUBGROUPING = NO TYPEDEF_HIDES_STRUCT = YES -SYMBOL_CACHE_SIZE = 0 EXTRACT_ALL = YES EXTRACT_PRIVATE = NO EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = NO EXTRACT_LOCAL_METHODS = YES EXTRACT_ANON_NSPACES = YES HIDE_UNDOC_MEMBERS = YES HIDE_UNDOC_CLASSES = YES HIDE_FRIEND_COMPOUNDS = YES HIDE_IN_BODY_DOCS = YES INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_MEMBERS_CTORS_1ST = NO SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_FILES = YES SHOW_NAMESPACES = YES FILE_VERSION_FILTER = LAYOUT_FILE = #--------------------------------------------------------------------------- QUIET = YES WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO WARN_FORMAT = WARN_LOGFILE = #--------------------------------------------------------------------------- INPUT = @srcdir@/../include/qb/ @srcdir@/../docs/ INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.h RECURSIVE = NO EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = EXCLUDE_SYMBOLS = EXAMPLE_PATH = @srcdir@/../examples EXAMPLE_PATTERNS = *.c EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- SOURCE_BROWSER = NO INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = YES REFERENCES_RELATION = YES REFERENCES_LINK_SOURCE = YES USE_HTAGS = NO VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = NO COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_TIMESTAMP = NO HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES HTML_DYNAMIC_SECTIONS = NO GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" DOCSET_BUNDLE_ID = org.doxygen.Project GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO CHM_INDEX_ENCODING = BINARY_TOC = NO TOC_EXPAND = YES GENERATE_QHP = NO QCH_FILE = QHP_NAMESPACE = QHP_VIRTUAL_FOLDER = doc QHP_CUST_FILTER_NAME = QHP_CUST_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS = QHG_LOCATION = DISABLE_INDEX = NO ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = NO -USE_INLINE_TREES = NO TREEVIEW_WIDTH = 250 FORMULA_FONTSIZE = 10 SEARCHENGINE = YES GENERATE_LATEX = YES LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4wide EXTRA_PACKAGES = LATEX_HEADER = PDF_HYPERLINKS = NO USE_PDFLATEX = NO LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO LATEX_SOURCE_CODE = NO GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- GENERATE_MAN = NO MAN_OUTPUT = . MAN_EXTENSION = .3 MAN_LINKS = NO #--------------------------------------------------------------------------- GENERATE_LATEX = NO GENERATE_RTF = NO GENERATE_XML = NO GENERATE_AUTOGEN_DEF = NO GENERATE_PERLMOD = NO #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = @srcdir@/../include INCLUDE_FILE_PATTERNS = *.h PREDEFINED = EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # # TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = NO PERL_PATH = #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES MSCGEN_PATH = HIDE_UNDOC_RELATIONS = YES HAVE_DOT = YES -DOT_FONTNAME = FreeSans +DOT_FONTNAME = DOT_FONTSIZE = 10 DOT_FONTPATH = CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES UML_LOOK = YES TEMPLATE_RELATIONS = YES INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO CALLER_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = png DOT_PATH = DOTFILE_DIRS = DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES diff --git a/docs/man.dox.in b/docs/man.dox.in index f88e216..1d3c73b 100644 --- a/docs/man.dox.in +++ b/docs/man.dox.in @@ -1,161 +1,160 @@ DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = libqb PROJECT_NUMBER = @VERSION@ OUTPUT_DIRECTORY = . CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = YES ALWAYS_DETAILED_SEC = YES INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = NO STRIP_FROM_PATH = STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = YES QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 8 ALIASES = OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO EXTENSION_MAPPING = BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO SIP_SUPPORT = NO IDL_PROPERTY_SUPPORT = NO DISTRIBUTE_GROUP_DOC = YES SUBGROUPING = NO TYPEDEF_HIDES_STRUCT = YES -SYMBOL_CACHE_SIZE = 0 EXTRACT_ALL = YES EXTRACT_PRIVATE = NO EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = NO EXTRACT_LOCAL_METHODS = YES EXTRACT_ANON_NSPACES = YES HIDE_UNDOC_MEMBERS = YES HIDE_UNDOC_CLASSES = YES HIDE_FRIEND_COMPOUNDS = YES HIDE_IN_BODY_DOCS = YES INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_MEMBERS_CTORS_1ST = NO SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO GENERATE_TODOLIST = NO GENERATE_TESTLIST = NO GENERATE_BUGLIST = NO GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_FILES = YES SHOW_NAMESPACES = YES FILE_VERSION_FILTER = LAYOUT_FILE = #--------------------------------------------------------------------------- QUIET = YES WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO WARN_FORMAT = WARN_LOGFILE = #--------------------------------------------------------------------------- INPUT = @srcdir@/../include/qb/ @srcdir@/../docs/ INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.h RECURSIVE = YES EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = EXCLUDE_SYMBOLS = EXAMPLE_PATH = EXAMPLE_PATTERNS = EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- SOURCE_BROWSER = NO INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = YES REFERENCES_RELATION = YES REFERENCES_LINK_SOURCE = YES USE_HTAGS = NO VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = NO COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- GENERATE_MAN = YES MAN_OUTPUT = . MAN_EXTENSION = .3 MAN_LINKS = YES GENERATE_HTML = NO #--------------------------------------------------------------------------- GENERATE_LATEX = NO GENERATE_RTF = NO GENERATE_XML = NO GENERATE_AUTOGEN_DEF = NO GENERATE_PERLMOD = NO #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = YES SEARCH_INCLUDES = YES INCLUDE_PATH = ../include INCLUDE_FILE_PATTERNS = *.h PREDEFINED = EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = NO #--------------------------------------------------------------------------- # # TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = NO PERL_PATH = #--------------------------------------------------------------------------- CLASS_DIAGRAMS = NO MSCGEN_PATH = HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO -DOT_FONTNAME = FreeSans +DOT_FONTNAME = DOT_FONTSIZE = 10 DOT_FONTPATH = CLASS_GRAPH = NO COLLABORATION_GRAPH = NO GROUP_GRAPHS = NO UML_LOOK = NO TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = NO INCLUDED_BY_GRAPH = NO CALL_GRAPH = NO CALLER_GRAPH = NO GRAPHICAL_HIERARCHY = NO DIRECTORY_GRAPH = NO DOT_IMAGE_FORMAT = png DOT_PATH = DOTFILE_DIRS = DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES diff --git a/include/qb/qbatomic.h b/include/qb/qbatomic.h index bd475b4..45c762e 100644 --- a/include/qb/qbatomic.h +++ b/include/qb/qbatomic.h @@ -1,207 +1,207 @@ /* * Copyright (C) 2003 Sebastian Wilhelmi * * 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 . */ /* * Copied from the glib code base (glib/gatomic.h) and namespaced * for libqb. */ #ifndef QB_ATOMIC_H_DEFINED #define QB_ATOMIC_H_DEFINED /* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif /* *INDENT-ON* */ #include #include #include /** * @file * Basic atomic integer and pointer operations * * The following functions can be used to atomically access integers and * pointers. They are implemented as inline assembler function on most * platforms and use slower fall-backs otherwise. Using them can sometimes * save you from using a performance-expensive pthread_mutex to protect the * integer or pointer. * * The most important usage is reference counting. Using * qb_atomic_int_inc() and qb_atomic_int_dec_and_test() makes reference * counting a very fast operation. * * You must not directly read integers or pointers concurrently * accessed by multiple threads, but use the atomic accessor functions * instead. That is, always use qb_atomic_int_get() and qb_atomic_pointer_get() - * for read outs. They provide the neccessary synchonization mechanisms + * for read outs. They provide the necessary synchonization mechanisms * like memory barriers to access memory locations concurrently. * * 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 qb_atomic_int_inc() and * qb_atomic_int_dec_and_test(). * * 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 qb_atomic_int_compare_and_exchange() or * qb_atomic_pointer_compare_and_exchange() respectively. */ void qb_atomic_init(void); /** * 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. * * @param atomic a pointer to an integer * @param val the value to add to *atomic * @return the value of *atomic before the addition. */ int32_t qb_atomic_int_exchange_and_add(volatile int32_t QB_GNUC_MAY_ALIAS * atomic, int32_t val); /** * Atomically adds val to the integer pointed to by atomic. * Also acts as a memory barrier. * * @param atomic a pointer to an integer * @param val the value to add to *atomic */ void qb_atomic_int_add(volatile int32_t QB_GNUC_MAY_ALIAS * atomic, int32_t val); /** * 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. * * @param atomic a pointer to an integer * @param oldval the assumed old value of *atomic * @param newval the new value of *atomic * * @return QB_TRUE, if *atomic was equal oldval. QB_FALSE otherwise. */ int32_t qb_atomic_int_compare_and_exchange(volatile int32_t QB_GNUC_MAY_ALIAS * atomic, int32_t oldval, int32_t newval); /** * 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. * * @param atomic a pointer to a void* * @param oldval the assumed old value of *atomic * @param newval the new value of *atomic * * @return QB_TRUE if atomic was equal oldval, else QB_FALSE. */ int32_t qb_atomic_pointer_compare_and_exchange(volatile void* QB_GNUC_MAY_ALIAS * atomic, void* oldval, void* newval); /** * Reads the value of the integer pointed to by atomic. * Also acts as a memory barrier. * * @param atomic a pointer to an integer * * @return the value of atomic */ int32_t qb_atomic_int_get(volatile int32_t QB_GNUC_MAY_ALIAS * atomic); /** * Sets the value of the integer pointed to by atomic. * Also acts as a memory barrier. * * @param atomic a pointer to an integer * @param newval the new value */ void qb_atomic_int_set(volatile int32_t QB_GNUC_MAY_ALIAS * atomic, int32_t newval); /** * Reads the value of the pointer pointed to by atomic. * Also acts as a memory barrier. * * @param atomic a pointer to a void*. * @return the value to add to atomic. */ void* qb_atomic_pointer_get(volatile void* QB_GNUC_MAY_ALIAS * atomic); /** * Sets the value of the pointer pointed to by atomic. * Also acts as a memory barrier. * * @param atomic a pointer to a void* * @param newval the new value * */ void qb_atomic_pointer_set(volatile void* QB_GNUC_MAY_ALIAS * atomic, void* newval); #ifndef QB_ATOMIC_OP_MEMORY_BARRIER_NEEDED #define qb_atomic_int_get(atomic) ((int32_t)*(atomic)) #define qb_atomic_int_set(atomic, newval) ((void) (*(atomic) = (newval))) #define qb_atomic_pointer_get(atomic) ((void*)*(atomic)) #define qb_atomic_pointer_set(atomic, newval) ((void*) (*(atomic) = (newval))) #else #define qb_atomic_int_get(atomic) \ ((void) sizeof (char* [sizeof (*(atomic)) == sizeof (int32_t) ? 1 : -1]), \ (qb_atomic_int_get) ((volatile int32_t QB_GNUC_MAY_ALIAS *) (volatile void *) (atomic))) #define qb_atomic_int_set(atomic, newval) \ ((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))) #define qb_atomic_pointer_get(atomic) \ ((void) sizeof (char* [sizeof (*(atomic)) == sizeof (void*) ? 1 : -1]), \ (qb_atomic_pointer_get) ((volatile void* QB_GNUC_MAY_ALIAS *) (volatile void *) (atomic))) #define qb_atomic_pointer_set(atomic, newval) \ ((void) sizeof (char* [sizeof (*(atomic)) == sizeof (void*) ? 1 : -1]), \ (qb_atomic_pointer_set) ((volatile void* QB_GNUC_MAY_ALIAS *) (volatile void *) (atomic), (newval))) #endif /* QB_ATOMIC_OP_MEMORY_BARRIER_NEEDED */ /** * Atomically increments the integer pointed to by atomic by 1. * * @param atomic a pointer to an integer. */ #define qb_atomic_int_inc(atomic) (qb_atomic_int_add ((atomic), 1)) /** * Atomically decrements the integer pointed to by atomic by 1. * * @param atomic a pointer to an integer * * @return QB_TRUE if the integer pointed to by atomic is 0 * after decrementing it */ #define qb_atomic_int_dec_and_test(atomic) \ (qb_atomic_int_exchange_and_add ((atomic), -1) == 1) /* *INDENT-OFF* */ #ifdef __cplusplus } #endif /* *INDENT-ON* */ #endif /* QB_ATOMIC_H_DEFINED */ diff --git a/include/qb/qbipc_common.h b/include/qb/qbipc_common.h index 0a4118c..2253941 100644 --- a/include/qb/qbipc_common.h +++ b/include/qb/qbipc_common.h @@ -1,66 +1,71 @@ /* * Copyright (c) 2010 Red Hat, Inc. * * All rights reserved. * * Author: Angus Salkeld * * 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 . */ #ifndef QB_IPC_COMMON_H_DEFINED #define QB_IPC_COMMON_H_DEFINED #include /* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif /* *INDENT-ON* */ +/** + * @file qbipc_common.h + * common types and definitions + */ + struct qb_ipc_request_header { int32_t id __attribute__ ((aligned(8))); int32_t size __attribute__ ((aligned(8))); } __attribute__ ((aligned(8))); struct qb_ipc_response_header { int32_t id __attribute__ ((aligned(8))); int32_t size __attribute__ ((aligned(8))); int32_t error __attribute__ ((aligned(8))); } __attribute__ ((aligned(8))); enum qb_ipc_type { QB_IPC_SOCKET, QB_IPC_SHM, QB_IPC_POSIX_MQ, QB_IPC_SYSV_MQ, QB_IPC_NATIVE, }; #define QB_IPC_MSG_NEW_MESSAGE 0 #define QB_IPC_MSG_USER_START QB_IPC_MSG_NEW_MESSAGE #define QB_IPC_MSG_AUTHENTICATE -1 #define QB_IPC_MSG_NEW_EVENT_SOCK -2 #define QB_IPC_MSG_DISCONNECT -3 /* *INDENT-OFF* */ #ifdef __cplusplus } #endif /* *INDENT-ON* */ #endif /* QB_IPC_COMMON_H_DEFINED */ diff --git a/include/qb/qbipcs.h b/include/qb/qbipcs.h index 9ef2aa6..6e6ef85 100644 --- a/include/qb/qbipcs.h +++ b/include/qb/qbipcs.h @@ -1,474 +1,474 @@ /* * Copyright (C) 2006-2009 Red Hat, Inc. * * Author: Steven Dake , * Angus Salkeld * * 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 . */ #ifndef QB_IPCS_H_DEFINED #define QB_IPCS_H_DEFINED /* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif /* *INDENT-ON* */ #include #include #include #include #include /** * @file qbipcs.h * * Server IPC API. * * @example ipcserver.c */ enum qb_ipcs_rate_limit { QB_IPCS_RATE_FAST, QB_IPCS_RATE_NORMAL, QB_IPCS_RATE_SLOW, QB_IPCS_RATE_OFF, QB_IPCS_RATE_OFF_2, }; struct qb_ipcs_connection; typedef struct qb_ipcs_connection qb_ipcs_connection_t; struct qb_ipcs_service; typedef struct qb_ipcs_service qb_ipcs_service_t; struct qb_ipcs_stats { uint32_t active_connections; uint32_t closed_connections; }; struct qb_ipcs_connection_stats { 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; }; 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); typedef int32_t (*qb_ipcs_dispatch_add_fn)(enum qb_loop_priority p, int32_t fd, int32_t events, void *data, qb_ipcs_dispatch_fn_t fn); typedef int32_t (*qb_ipcs_dispatch_mod_fn)(enum qb_loop_priority p, int32_t fd, int32_t events, void *data, qb_ipcs_dispatch_fn_t fn); typedef int32_t (*qb_ipcs_dispatch_del_fn)(int32_t fd); typedef int32_t (*qb_ipcs_job_add_fn)(enum qb_loop_priority p, void *data, qb_loop_job_dispatch_fn dispatch_fn); struct qb_ipcs_poll_handlers { qb_ipcs_job_add_fn job_add; qb_ipcs_dispatch_add_fn dispatch_add; qb_ipcs_dispatch_mod_fn dispatch_mod; qb_ipcs_dispatch_del_fn dispatch_del; }; /** * This callback is to check whether you want to accept a new connection. * * 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 If connection state data is allocated as a result of this callback * being invoked, that data must be freed in the destroy callback. Just because * the accept callback returns 0, that does not guarantee the * create and closed callback functions will follow. * @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); /** * This is called after a new connection has been created. * * @note A client connection is not considered connected until * this callback is invoked. */ typedef void (*qb_ipcs_connection_created_fn) (qb_ipcs_connection_t *c); /** * This is called after a connection has been disconnected. * * @note This callback will only be invoked if the connection is * successfully created. * @note if you return anything but 0 this function will be * repeativily called (until 0 is returned). */ typedef int32_t (*qb_ipcs_connection_closed_fn) (qb_ipcs_connection_t *c); /** * This is called just before a connection is freed. */ typedef void (*qb_ipcs_connection_destroyed_fn) (qb_ipcs_connection_t *c); /** * This is the message processing calback. * It is called with the message data. */ typedef int32_t (*qb_ipcs_msg_process_fn) (qb_ipcs_connection_t *c, void *data, size_t size); struct qb_ipcs_service_handlers { qb_ipcs_connection_accept_fn connection_accept; qb_ipcs_connection_created_fn connection_created; qb_ipcs_msg_process_fn msg_process; qb_ipcs_connection_closed_fn connection_closed; qb_ipcs_connection_destroyed_fn connection_destroyed; }; /** * Create a new IPC server. * * @param name for clients to connect to. * @param service_id an integer to associate with the service * @param type transport type. * @param handlers callbacks. * @return the new service instance. */ qb_ipcs_service_t* qb_ipcs_create(const char *name, int32_t service_id, enum qb_ipc_type type, struct qb_ipcs_service_handlers *handlers); /** * Increase the reference counter on the service object. * * @param s service instance */ void qb_ipcs_ref(qb_ipcs_service_t *s); /** * Decrease the reference counter on the service object. * * @param s service instance */ void qb_ipcs_unref(qb_ipcs_service_t *s); /** * Set your poll callbacks. * * @param s service instance * @param handlers the handlers that you want ipcs to use. */ void qb_ipcs_poll_handlers_set(qb_ipcs_service_t* s, struct qb_ipcs_poll_handlers *handlers); /** * Associate a "user" pointer with this service. * * @param s service instance * @param context the pointer to associate with this service. * @see qb_ipcs_service_context_get() */ void qb_ipcs_service_context_set(qb_ipcs_service_t* s, void *context); /** * Get the context (set previously) * * @param s service instance * @return the context * @see qb_ipcs_service_context_set() */ void *qb_ipcs_service_context_get(qb_ipcs_service_t* s); /** * run the new IPC server. * @param s service instance * @return 0 == ok; -errno to indicate a failure. Service is destroyed on failure. */ int32_t qb_ipcs_run(qb_ipcs_service_t* s); /** * Destroy the IPC server. * * @param s service instance to destroy */ void qb_ipcs_destroy(qb_ipcs_service_t* s); /** - * Limit the incomming request rate. + * Limit the incoming request rate. * @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); /** - * Send a response to a incomming request. + * Send a response to a incoming request. * * @param c connection instance * @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); /** - * Send a response to a incomming request. + * Send a response to a incoming request. * * @param c connection instance * @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. * * @note When send returns -EMSGSIZE, this means the msg is too * large and will never succeed. To determine the max msg size * a client can be sent, use qb_ipcs_connection_get_buffer_size() */ 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. * * @param c connection instance * @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. * * @note When send returns -EMSGSIZE, this means the msg is too * large and will never succeed. To determine the max msg size * a client can be sent, use qb_ipcs_connection_get_buffer_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. * * @param c connection instance * @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. * * @note When send returns -EMSGSIZE, this means the msg is too * large and will never succeed. To determine the max msg size * a client can be sent, use qb_ipcs_connection_get_buffer_size() */ 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. * * @param c connection instance */ void qb_ipcs_connection_ref(qb_ipcs_connection_t *c); /** * Decrement the connection's reference counter. * * @param c connection instance */ void qb_ipcs_connection_unref(qb_ipcs_connection_t *c); /** * Disconnect from this client. * * @param c connection instance */ void qb_ipcs_disconnect(qb_ipcs_connection_t *c); /** * Get the service id related to this connection's service. * (as passed into qb_ipcs_create() * * @return service id. */ int32_t qb_ipcs_service_id_get(qb_ipcs_connection_t *c); /** * Associate a "user" pointer with this connection. * * @param context the point to associate with this connection. * @param c connection instance * @see qb_ipcs_context_get() */ void qb_ipcs_context_set(qb_ipcs_connection_t *c, void *context); /** * Get the context (set previously) * * @param c connection instance * @return the context * @see qb_ipcs_context_set() */ void *qb_ipcs_context_get(qb_ipcs_connection_t *c); /** * Get the context previously set on the service backing this connection * * @param c connection instance * @return the context * @see qb_ipcs_service_context_set */ void *qb_ipcs_connection_service_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 * @return 0 == ok; -errno to indicate a failure */ 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. * * @param stats (out) the statistics structure * @param clear_after_read clear stats after copying them into stats * @param pt service instance * @return 0 == ok; -errno to indicate a failure */ int32_t qb_ipcs_stats_get(qb_ipcs_service_t* pt, struct qb_ipcs_stats* stats, int32_t clear_after_read); /** * Get the first connection. * * @note call qb_ipcs_connection_unref() after using the connection. * * @param pt service instance * @return first connection */ qb_ipcs_connection_t * qb_ipcs_connection_first_get(qb_ipcs_service_t* pt); /** * Get the next connection. * * @note call qb_ipcs_connection_unref() after using the connection. * * @param pt service instance * @param current current connection * @return next connection */ 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); /** * Retrieve the connection ipc buffer size. This reflects the * largest size msg that can be sent or received. * * @param conn connection instance * @return msg size in bytes, negative value on error. */ int32_t qb_ipcs_connection_get_buffer_size(qb_ipcs_connection_t *conn); /** * Enforce the max buffer size clients must use from the server side. * * @note Setting this will force client connections to use at least * max_buf_size bytes as their buffer size. If this value is not set * on the server, the clients enforce their own buffer sizes. * * @param s ipc server instance * @param max_buf_size represented in bytes */ void qb_ipcs_enforce_buffer_size(qb_ipcs_service_t *s, uint32_t max_buf_size); /* *INDENT-OFF* */ #ifdef __cplusplus } #endif /* *INDENT-ON* */ #endif /* QB_IPCS_H_DEFINED */ diff --git a/include/qb/qbutil.h b/include/qb/qbutil.h index 87102e8..bfce349 100644 --- a/include/qb/qbutil.h +++ b/include/qb/qbutil.h @@ -1,298 +1,298 @@ /* * Copyright (C) 2010 Red Hat, Inc. * * Author: Angus Salkeld * * 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 . */ #ifndef QB_UTIL_H_DEFINED #define QB_UTIL_H_DEFINED /* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif /* *INDENT-ON* */ #include #include #ifndef S_SPLINT_S #include #endif /* S_SPLINT_S */ #include /** * @file qbutil.h - * @author Angus Salkeld - * * These are some convience functions used throughout libqb. * + * @author Angus Salkeld + * * @par Locking * - qb_thread_lock_create() * - qb_thread_lock() * - qb_thread_trylock() * - qb_thread_unlock() * - qb_thread_lock_destroy() * * @par Time functions * - qb_timespec_add_ms() * - qb_util_nano_current_get() * - qb_util_nano_monotonic_hz() * - qb_util_nano_from_epoch_get() * - qb_util_timespec_from_epoch_get() * * @par Basic Stopwatch * @code * 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); * @endcode * * @par Stopwatch with splits * Setup a stopwatch with space for 3 splits. * * @code * 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); * @endcode * */ /** * @typedef qb_thread_lock_type_t * QB_THREAD_LOCK_SHORT is a short term lock (spinlock if available on your system) * QB_THREAD_LOCK_LONG is a mutex */ typedef enum { QB_THREAD_LOCK_SHORT, QB_THREAD_LOCK_LONG, } qb_thread_lock_type_t; struct qb_thread_lock_s; typedef struct qb_thread_lock_s qb_thread_lock_t; /** * Create a new lock of the given type. * @param type QB_THREAD_LOCK_SHORT == spinlock (where available, else mutex) * QB_THREAD_LOCK_LONG == mutex * @return pointer to qb_thread_lock_type_t or NULL on error. */ qb_thread_lock_t *qb_thread_lock_create(qb_thread_lock_type_t type); /** * Calls either pthread_mutex_lock() or pthread_spin_lock(). */ int32_t qb_thread_lock(qb_thread_lock_t * tl); /** * Calls either pthread_mutex_trylock() or pthread_spin_trylock(). */ int32_t qb_thread_trylock(qb_thread_lock_t * tl); /** * Calls either pthread_mutex_unlock() or pthread_spin_unlock. */ int32_t qb_thread_unlock(qb_thread_lock_t * tl); /** * Calls either pthread_mutex_destro() or pthread_spin_destroy(). */ int32_t qb_thread_lock_destroy(qb_thread_lock_t * tl); typedef void (*qb_util_log_fn_t) (const char *file_name, int32_t file_line, int32_t severity, const char *msg); /** * Use this function to output libqb internal log message as you wish. */ void qb_util_set_log_function(qb_util_log_fn_t fn) QB_GNUC_DEPRECATED; /** * Add milliseconds onto the timespec. * @param ts the ts to add to * @param ms the amount of milliseconds to increment ts */ void qb_timespec_add_ms(struct timespec *ts, int32_t ms); /** * Get the current number of nano secounds produced * by the systems incrementing clock (CLOCK_MONOTOMIC * if available). */ uint64_t qb_util_nano_current_get(void); /** * Get the frequence of the clock used in * qb_util_nano_current_get(). */ uint64_t qb_util_nano_monotonic_hz(void); /** * Get the time in nano seconds since epoch. */ uint64_t qb_util_nano_from_epoch_get(void); /** * Get the time in timespec since epoch. * @param ts (out) the timespec * @return status (0 == ok, -errno on error) */ void qb_util_timespec_from_epoch_get(struct timespec *ts); /** * strerror_r replacement. */ char *qb_strerror_r(int errnum, char *buf, size_t buflen); typedef struct qb_util_stopwatch qb_util_stopwatch_t; #define QB_UTIL_SW_OVERWRITE 0x01 /** * Create a Stopwatch (to time operations) */ qb_util_stopwatch_t * qb_util_stopwatch_create(void); /** * Free the stopwatch */ void qb_util_stopwatch_free(qb_util_stopwatch_t *sw); /** * Start the stopwatch * * This also acts as a reset. Essentially it sets the * starting time and clears the splits. */ void qb_util_stopwatch_start(qb_util_stopwatch_t *sw); /** * Stop the stopwatch * * This just allows you to get the elapsed time. So * you can call this multiple times. Do not call qb_util_stopwatch_start() * unless you want to reset the stopwatch. */ void qb_util_stopwatch_stop(qb_util_stopwatch_t *sw); /** * Get the elapsed time in micro seconds. * * (it must have been started and stopped). */ uint64_t qb_util_stopwatch_us_elapsed_get(qb_util_stopwatch_t *sw); /** * Get the elapsed time in seconds. * * (it must have been started and stopped). */ float qb_util_stopwatch_sec_elapsed_get(qb_util_stopwatch_t *sw); /** * * @param sw the stopwatch * @param max_splits maximum number of time splits * @param options (0 or QB_UTIL_SW_OVERWRITE ) * @retval 0 on success * @retval -errno on failure */ int32_t qb_util_stopwatch_split_ctl(qb_util_stopwatch_t *sw, uint32_t max_splits, uint32_t options); /** * Create a new time split (or lap time) * * @param sw the stopwatch * @retval the relative split time in micro seconds * @retval 0 if no more splits available */ uint64_t qb_util_stopwatch_split(qb_util_stopwatch_t *sw); /** * Get the last split index to be used by * qb_util_stopwatch_time_split_get() * * @note this is zero based * * @param sw the stopwatch * @return the last entry index */ uint32_t qb_util_stopwatch_split_last(qb_util_stopwatch_t *sw); /** * Read the time split (in us) from "receint" to "older". * * If older == receint then the cumulated split will be * returned (from the stopwatch start). * * @param sw the stopwatch * @param receint split * @param older split * @retval the split time in micro seconds * @retval 0 if not a valid split */ uint64_t qb_util_stopwatch_time_split_get(qb_util_stopwatch_t *sw, uint32_t receint, uint32_t older); /* *INDENT-OFF* */ #ifdef __cplusplus } #endif /* __cplusplus */ /* *INDENT-ON* */ #endif /* QB_UTIL_H_DEFINED */