Initial contribution

This commit is contained in:
Michiel Beemster 2018-04-10 17:03:59 +02:00
parent 7b5cc4fa59
commit 11d9ce37aa
580 changed files with 155133 additions and 162 deletions

68
src/core/CMakeLists.txt Normal file
View file

@ -0,0 +1,68 @@
#
# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0 which is available at
# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
# v. 1.0 which is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
#
find_package(Abstraction REQUIRED)
include (GenerateExportHeader)
FUNCTION(PREPEND var prefix)
SET(listVar "")
FOREACH(f ${ARGN})
LIST(APPEND listVar "${prefix}/${f}")
ENDFOREACH(f)
SET(${var} "${listVar}" PARENT_SCOPE)
ENDFUNCTION(PREPEND)
option(DDSC_SHARED "Build DDSC as a shared library" ON)
if(DDSC_SHARED AND ((NOT DEFINED BUILD_SHARED_LIBS) OR BUILD_SHARED_LIBS))
# BUILD_SHARED_LIBS is set to off by for example VxWorks DKM environment
add_library(ddsc SHARED "")
else()
if(DDSC_SHARED)
message(STATUS "Option DDSC_SHARED ignored. Only static libraries supported on this platform.")
endif()
add_library(ddsc "")
endif()
include(ddsi/CMakeLists.txt)
include(ddsc/CMakeLists.txt)
include(security/CMakeLists.txt)
target_link_libraries(ddsc PRIVATE util)
target_link_libraries(ddsc PRIVATE OSAPI)
# SOVERSION should increase on incompatible ABI change
set_target_properties(ddsc PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR})
get_target_property(os_api_src_dir OSAPI SOURCE_DIR)
# We need to expose some of the OS headers as well.
target_include_directories(ddsc
PUBLIC
"$<BUILD_INTERFACE:${os_api_src_dir}/include>")
set_target_file_ids(ddsc)
# Create a pseudo-target that other targets (i.e. examples, tests) can depend
# on and can also be provided as import-target by a package-file when building
# those targets outside the regular Cyclone build-tree (i.e. the installed tree)
add_library(${CMAKE_PROJECT_NAME}::ddsc ALIAS ddsc)
install(
TARGETS ddsc
EXPORT "${CMAKE_PROJECT_NAME}"
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT lib
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT lib
)

32
src/core/ddsc/.fileids Normal file
View file

@ -0,0 +1,32 @@
# ddsc sources
40 src/dds_alloc.c
41 src/dds_coherent.c
42 src/dds_iid.c
43 src/dds_participant.c
44 src/dds_reader.c
45 src/dds_thread.c
46 src/dds_writer.c
47 src/dds_init.c
48 src/dds_publisher.c
49 src/dds_rhc.c
50 src/dds_time.c
51 src/q_osplser.c
52 src/dds_domain.c
53 src/dds_instance.c
54 src/dds_qos.c
55 src/dds_tkmap.c
56 src/dds_entity.c
57 src/dds_key.c
58 src/dds_querycond.c
59 src/dds_topic.c
60 src/dds_err.c
61 src/dds_listener.c
62 src/dds_read.c
63 src/dds_stream.c
64 src/dds_waitset.c
65 src/dds_log.c
66 src/dds_readcond.c
67 src/dds_subscriber.c
68 src/dds_write.c
69 src/dds_report.c
70 src/dds_builtin.c

View file

@ -0,0 +1,146 @@
#
# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0 which is available at
# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
# v. 1.0 which is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
#
PREPEND(srcs_ddsc "${CMAKE_CURRENT_LIST_DIR}/src"
dds_alloc.c
dds_builtin.c
dds_coherent.c
dds_iid.c
dds_participant.c
dds_reader.c
dds_writer.c
dds_init.c
dds_publisher.c
dds_rhc.c
dds_time.c
q_osplser.c
dds_domain.c
dds_instance.c
dds_qos.c
dds_tkmap.c
dds_entity.c
dds_key.c
dds_querycond.c
dds_topic.c
dds_report.c
dds_err.c
dds_listener.c
dds_read.c
dds_stream.c
dds_waitset.c
dds_log.c
dds_readcond.c
dds_subscriber.c
dds_write.c
)
PREPEND(hdrs_public_ddsc "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include/ddsc>$<INSTALL_INTERFACE:include/ddsc>"
dds.h
dds_public_error.h
dds_public_impl.h
dds_public_listener.h
dds_public_log.h
dds_public_qos.h
dds_public_status.h
dds_public_stream.h
dds_public_time.h
)
PREPEND(hdrs_private_ddsc "${CMAKE_CURRENT_LIST_DIR}/src"
dds__alloc.h
dds__builtin.h
dds__domain.h
dds__entity.h
dds__iid.h
dds__init.h
dds__key.h
dds__listener.h
dds__participant.h
dds__publisher.h
dds__qos.h
dds__querycond.h
dds__readcond.h
dds__reader.h
dds__report.h
dds__rhc.h
dds__stream.h
dds__subscriber.h
dds__tkmap.h
dds__topic.h
dds__types.h
dds__write.h
dds__writer.h
q__osplser.h
)
configure_file(
"${CMAKE_CURRENT_LIST_DIR}/cmake/ddsc_project.h.in"
"include/ddsc/ddsc_project.h")
generate_export_header(
ddsc
BASE_NAME DDS
EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/include/ddsc/dds_export.h"
)
target_include_directories(ddsc
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>")
# Generate builtin-topic sources
set(IDLC_ARGS "-dll" "FOO,ddsc/dds_export.h")
idlc_generate(BuiltinTypes ddsc/src/dds_dcps_builtintopics.idl ddsc/src/dds_builtinTopics.idl)
set(IDLC_ARGS)
target_link_libraries(ddsc PRIVATE BuiltinTypes)
target_include_directories(ddsc
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>")
target_sources(ddsc
PRIVATE
${srcs_ddsc}
${hdrs_private_ddsc}
"include/ddsc/ddsc_project.h"
PUBLIC
${hdrs_public_ddsc}
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>$<INSTALL_INTERFACE:include>/ddsc/dds_export.h"
)
target_include_directories(ddsc
PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/../security/include>"
PRIVATE
"${CMAKE_CURRENT_LIST_DIR}/src")
install(
DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/include/ddsc"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
COMPONENT dev)
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/include/ddsc/dds_export.h"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ddsc"
COMPONENT dev)
install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/dds_dcps_builtintopics.h"
"${CMAKE_CURRENT_BINARY_DIR}/dds_builtinTopics.h"
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ddsc"
COMPONENT dev)
# TODO: improve test inclusion.
if((BUILD_TESTING) AND ((NOT DEFINED MSVC_VERSION) OR (MSVC_VERSION GREATER "1800")))
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/tests")
endif()

View file

@ -0,0 +1,25 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef DDSC_PROJECT_H
#define DDSC_PROJECT_H
#define DDSC_VERSION "@CycloneDDS_VERSION@"
#define DDSC_VERSION_MAJOR @CycloneDDS_VERSION_MAJOR@
#define DDSC_VERSION_MINOR @CycloneDDS_VERSION_MINOR@
#define DDSC_VERSION_PATCH @CycloneDDS_VERSION_PATCH@
#define DDSC_VERSION_TWEAK @CycloneDDS_VERSION_TWEAK@
#define DDSC_PROJECT_NAME_NOSPACE_CAPS "@CMAKE_PROJECT_NAME_CAPS@"
#define DDSC_PROJECT_NAME_NOSPACE_SMALL "@CMAKE_PROJECT_NAME_SMALL@"
#define DDSC_PROJECT_NAME_NOSPACE "@CMAKE_PROJECT_NAME@"
#define DDSC_PROJECT_NAME "@CMAKE_PROJECT_NAME@"
#endif /* DDSC_PROJECT_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,87 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
/* TODO: do we really need to expose this as an API? */
/** @file
*
* @brief DDS C Allocation API
*
* This header file defines the public API of allocation convenience functions
* in the CycloneDDS C language binding.
*/
#ifndef DDS_ALLOC_H
#define DDS_ALLOC_H
#include "os/os_public.h"
#include "ddsc/dds_export.h"
#if defined (__cplusplus)
extern "C" {
#endif
struct dds_topic_descriptor;
struct dds_sequence;
#define DDS_FREE_KEY_BIT 0x01
#define DDS_FREE_CONTENTS_BIT 0x02
#define DDS_FREE_ALL_BIT 0x04
typedef enum
{
DDS_FREE_ALL = DDS_FREE_KEY_BIT | DDS_FREE_CONTENTS_BIT | DDS_FREE_ALL_BIT,
DDS_FREE_CONTENTS = DDS_FREE_KEY_BIT | DDS_FREE_CONTENTS_BIT,
DDS_FREE_KEY = DDS_FREE_KEY_BIT
}
dds_free_op_t;
typedef struct dds_allocator
{
/* Behaviour as C library malloc, realloc and free */
void * (*malloc) (size_t size);
void * (*realloc) (void *ptr, size_t size); /* if needed */
void (*free) (void *ptr);
}
dds_allocator_t;
DDS_EXPORT void dds_set_allocator (const dds_allocator_t * __restrict n, dds_allocator_t * __restrict o);
typedef struct dds_aligned_allocator
{
/* size is a multiple of align, align is a power of 2 no less than
the machine's page size, returned pointer MUST be aligned to at
least align. */
void * (*alloc) (size_t size, size_t align);
void (*free) (size_t size, void *ptr);
}
dds_aligned_allocator_t;
DDS_EXPORT void dds_set_aligned_allocator (const dds_aligned_allocator_t * __restrict n, dds_aligned_allocator_t * __restrict o);
DDS_EXPORT void * dds_alloc (size_t size);
DDS_EXPORT void * dds_realloc (void * ptr, size_t size);
DDS_EXPORT void * dds_realloc_zero (void * ptr, size_t size);
DDS_EXPORT void dds_free (void * ptr);
typedef void * (*dds_alloc_fn_t) (size_t);
typedef void * (*dds_realloc_fn_t) (void *, size_t);
typedef void (*dds_free_fn_t) (void *);
DDS_EXPORT char * dds_string_alloc (size_t size);
DDS_EXPORT char * dds_string_dup (const char * str);
DDS_EXPORT void dds_string_free (char * str);
DDS_EXPORT void dds_sample_free (void * sample, const struct dds_topic_descriptor * desc, dds_free_op_t op);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,155 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
/** @file
*
* @brief DDS C Error API
*
* This header file defines the public API of error values and convenience
* functions in the CycloneDDS C language binding.
*/
#ifndef DDS_ERROR_H
#define DDS_ERROR_H
#include "os/os_public.h"
#include "ddsc/dds_export.h"
#if defined (__cplusplus)
extern "C" {
#endif
/* Error masks for returned status values */
#define DDS_ERR_NR_MASK 0x000000ff
#define DDS_ERR_LINE_MASK 0x003fff00
#define DDS_ERR_FILE_ID_MASK 0x7fc00000
/*
State is unchanged following a function call returning an error
other than UNSPECIFIED, OUT_OF_RESOURCES and ALREADY_DELETED.
Error handling functions. Three components to returned int status value.
1 - The DDS_ERR_xxx error number
2 - The file identifier
3 - The line number
All functions return >= 0 on success, < 0 on error
*/
/** @name Return codes
@{**/
#define DDS_RETCODE_OK 0 /**< Success */
#define DDS_RETCODE_ERROR 1 /**< Non specific error */
#define DDS_RETCODE_UNSUPPORTED 2 /**< Feature unsupported */
#define DDS_RETCODE_BAD_PARAMETER 3 /**< Bad parameter value */
#define DDS_RETCODE_PRECONDITION_NOT_MET 4 /**< Precondition for operation not met */
#define DDS_RETCODE_OUT_OF_RESOURCES 5 /**< When an operation fails because of a lack of resources */
#define DDS_RETCODE_NOT_ENABLED 6 /**< When a configurable feature is not enabled */
#define DDS_RETCODE_IMMUTABLE_POLICY 7 /**< When an attempt is made to modify an immutable policy */
#define DDS_RETCODE_INCONSISTENT_POLICY 8 /**< When a policy is used with inconsistent values */
#define DDS_RETCODE_ALREADY_DELETED 9 /**< When an attempt is made to delete something more than once */
#define DDS_RETCODE_TIMEOUT 10 /**< When a timeout has occurred */
#define DDS_RETCODE_NO_DATA 11 /**< When expected data is not provided */
#define DDS_RETCODE_ILLEGAL_OPERATION 12 /**< When a function is called when it should not be */
#define DDS_RETCODE_NOT_ALLOWED_BY_SECURITY 13 /**< When credentials are not enough to use the function */
/** @}*/
/* For backwards compatability */
#define DDS_SUCCESS DDS_RETCODE_OK
/** @name DDS_Error_Type
@{**/
#define DDS_CHECK_REPORT 0x01
#define DDS_CHECK_FAIL 0x02
#define DDS_CHECK_EXIT 0x04
/** @}*/
/* Error code handling functions */
/** @name Macros for error handling
@{**/
#define DDS_TO_STRING(n) #n
#define DDS_INT_TO_STRING(n) DDS_TO_STRING(n)
/** @}*/
/** Macro to extract error number */
#define dds_err_nr(e) ((-(e)) & DDS_ERR_NR_MASK)
/** Macro to extract line number */
#define dds_err_line(e) (((-(e)) & DDS_ERR_LINE_MASK) >> 8)
/** Macro to extract file identifier */
#define dds_err_file_id(e) (((-(e)) & DDS_ERR_FILE_ID_MASK) >> 22)
/**
* @brief Takes the error value and outputs a string corresponding to it.
*
* @param[in] err Error value to be converted to a string
* @returns String corresponding to the error value
*/
DDS_EXPORT const char * dds_err_str (dds_return_t err);
/**
* @brief Takes the error number, error type and filename and line number and formats it to
* a string which can be used for debugging.
*
* @param[in] err Error value
* @param[in] flags Indicates Fail, Exit or Report
* @param[in] where File and line number
* @returns true - True
* @returns false - False
*/
DDS_EXPORT bool dds_err_check (dds_return_t err, unsigned flags, const char * where);
/** Macro that defines dds_err_check function */
#define DDS_ERR_CHECK(e, f) (dds_err_check ((e), (f), __FILE__ ":" DDS_INT_TO_STRING(__LINE__)))
/* Failure handling */
/** Failure handler */
typedef void (*dds_fail_fn) (const char *, const char *);
/** Macro that defines dds_fail function */
#define DDS_FAIL(m) (dds_fail (m, __FILE__ ":" DDS_INT_TO_STRING (__LINE__)))
/**
* @brief Set the failure function
*
* @param[in] fn Function to invoke on failure
*/
DDS_EXPORT void dds_fail_set (dds_fail_fn fn);
/**
* @brief Get the failure function
*
* @returns Failure function
*/
DDS_EXPORT dds_fail_fn dds_fail_get (void);
/**
* @brief Handles failure through an installed failure handler
*
* @params[in] msg String containing failure message
* @params[in] where String containing file and location
*/
DDS_EXPORT void dds_fail (const char * msg, const char * where);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,210 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
/* TODO: do we really need to expose all of this as an API? maybe some, but all? */
/** @file
*
* @brief DDS C Implementation API
*
* This header file defines the public API for all kinds of things in the
* CycloneDDS C language binding.
*/
#ifndef DDS_IMPL_H
#define DDS_IMPL_H
#include "ddsc/dds_public_alloc.h"
#include "ddsc/dds_public_stream.h"
#include "os/os_public.h"
#include "ddsc/dds_export.h"
#if defined (__cplusplus)
extern "C" {
#endif
typedef struct dds_sequence
{
uint32_t _maximum;
uint32_t _length;
uint8_t * _buffer;
bool _release;
}
dds_sequence_t;
#define DDS_LENGTH_UNLIMITED -1
typedef struct dds_key_descriptor
{
const char * m_name;
uint32_t m_index;
}
dds_key_descriptor_t;
/*
Topic definitions are output by a preprocessor and have an
implementation-private definition. The only thing exposed on the
API is a pointer to the "topic_descriptor_t" struct type.
*/
typedef struct dds_topic_descriptor
{
const size_t m_size; /* Size of topic type */
const uint32_t m_align; /* Alignment of topic type */
const uint32_t m_flagset; /* Flags */
const uint32_t m_nkeys; /* Number of keys (can be 0) */
const char * m_typename; /* Type name */
const dds_key_descriptor_t * m_keys; /* Key descriptors (NULL iff m_nkeys 0) */
const uint32_t m_nops; /* Number of ops in m_ops */
const uint32_t * m_ops; /* Marshalling meta data */
const char * m_meta; /* XML topic description meta data */
}
dds_topic_descriptor_t;
/* Topic descriptor flag values */
#define DDS_TOPIC_NO_OPTIMIZE 0x0001
#define DDS_TOPIC_FIXED_KEY 0x0002
/*
Masks for read condition, read, take: there is only one mask here,
which combines the sample, view and instance states.
*/
#define DDS_READ_SAMPLE_STATE 1u
#define DDS_NOT_READ_SAMPLE_STATE 2u
#define DDS_ANY_SAMPLE_STATE (1u | 2u)
#define DDS_NEW_VIEW_STATE 4u
#define DDS_NOT_NEW_VIEW_STATE 8u
#define DDS_ANY_VIEW_STATE (4u | 8u)
#define DDS_ALIVE_INSTANCE_STATE 16u
#define DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE 32u
#define DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE 64u
#define DDS_ANY_INSTANCE_STATE (16u | 32u | 64u)
#define DDS_ANY_STATE (DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE)
#define DDS_DOMAIN_DEFAULT -1
#define DDS_HANDLE_NIL 0
#define DDS_ENTITY_NIL 0
#define DDS_ENTITY_KIND_MASK (0x7F000000) /* Should be same as UT_HANDLE_KIND_MASK. */
typedef enum dds_entity_kind
{
DDS_KIND_DONTCARE = 0x00000000,
DDS_KIND_TOPIC = 0x01000000,
DDS_KIND_PARTICIPANT = 0x02000000,
DDS_KIND_READER = 0x03000000,
DDS_KIND_WRITER = 0x04000000,
DDS_KIND_SUBSCRIBER = 0x05000000,
DDS_KIND_PUBLISHER = 0x06000000,
DDS_KIND_COND_READ = 0x07000000,
DDS_KIND_COND_QUERY = 0x08000000,
DDS_KIND_WAITSET = 0x09000000,
DDS_KIND_INTERNAL = 0x0A000000,
}
dds_entity_kind_t;
/* Handles are opaque pointers to implementation types */
typedef uint64_t dds_instance_handle_t;
typedef int32_t dds_domainid_t;
/* Topic encoding instruction types */
#define DDS_OP_RTS 0x00000000
#define DDS_OP_ADR 0x01000000
#define DDS_OP_JSR 0x02000000
#define DDS_OP_JEQ 0x03000000
/* Core type flags
1BY : One byte simple type
2BY : Two byte simple type
4BY : Four byte simple type
8BY : Eight byte simple type
STR : String
BST : Bounded string
SEQ : Sequence
ARR : Array
UNI : Union
STU : Struct
*/
#define DDS_OP_VAL_1BY 0x01
#define DDS_OP_VAL_2BY 0x02
#define DDS_OP_VAL_4BY 0x03
#define DDS_OP_VAL_8BY 0x04
#define DDS_OP_VAL_STR 0x05
#define DDS_OP_VAL_BST 0x06
#define DDS_OP_VAL_SEQ 0x07
#define DDS_OP_VAL_ARR 0x08
#define DDS_OP_VAL_UNI 0x09
#define DDS_OP_VAL_STU 0x0a
#define DDS_OP_TYPE_1BY (DDS_OP_VAL_1BY << 16)
#define DDS_OP_TYPE_2BY (DDS_OP_VAL_2BY << 16)
#define DDS_OP_TYPE_4BY (DDS_OP_VAL_4BY << 16)
#define DDS_OP_TYPE_8BY (DDS_OP_VAL_8BY << 16)
#define DDS_OP_TYPE_STR (DDS_OP_VAL_STR << 16)
#define DDS_OP_TYPE_SEQ (DDS_OP_VAL_SEQ << 16)
#define DDS_OP_TYPE_ARR (DDS_OP_VAL_ARR << 16)
#define DDS_OP_TYPE_UNI (DDS_OP_VAL_UNI << 16)
#define DDS_OP_TYPE_STU (DDS_OP_VAL_STU << 16)
#define DDS_OP_TYPE_BST (DDS_OP_VAL_BST << 16)
#define DDS_OP_TYPE_BOO DDS_OP_TYPE_1BY
#define DDS_OP_SUBTYPE_BOO DDS_OP_SUBTYPE_1BY
#define DDS_OP_SUBTYPE_1BY (DDS_OP_VAL_1BY << 8)
#define DDS_OP_SUBTYPE_2BY (DDS_OP_VAL_2BY << 8)
#define DDS_OP_SUBTYPE_4BY (DDS_OP_VAL_4BY << 8)
#define DDS_OP_SUBTYPE_8BY (DDS_OP_VAL_8BY << 8)
#define DDS_OP_SUBTYPE_STR (DDS_OP_VAL_STR << 8)
#define DDS_OP_SUBTYPE_SEQ (DDS_OP_VAL_SEQ << 8)
#define DDS_OP_SUBTYPE_ARR (DDS_OP_VAL_ARR << 8)
#define DDS_OP_SUBTYPE_UNI (DDS_OP_VAL_UNI << 8)
#define DDS_OP_SUBTYPE_STU (DDS_OP_VAL_STU << 8)
#define DDS_OP_SUBTYPE_BST (DDS_OP_VAL_BST << 8)
#define DDS_OP_FLAG_KEY 0x01
#define DDS_OP_FLAG_DEF 0x02
/**
* Description : Enable or disable write batching. Overrides default configuration
* setting for write batching (DDSI2E/Internal/WriteBatch).
*
* Arguments :
* -# enable Enables or disables write batching for all writers.
*/
DDS_EXPORT void dds_write_set_batch (bool enable);
/**
* Description : Install tcp/ssl and encryption support. Depends on openssl.
*
* Arguments :
* -# None
*/
DDS_EXPORT void dds_ssl_plugin (void);
/**
* Description : Install client durability support. Depends on OSPL server.
*
* Arguments :
* -# None
*/
DDS_EXPORT void dds_durability_plugin (void);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,323 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
/** @file
*
* @brief DDS C Listener API
*
* This header file defines the public API of listeners in the
* CycloneDDS C language binding.
*/
#ifndef _DDS_PUBLIC_LISTENER_H_
#define _DDS_PUBLIC_LISTENER_H_
#include "ddsc/dds_export.h"
#include "ddsc/dds_public_impl.h"
#include "ddsc/dds_public_status.h"
#include "os/os_public.h"
#if defined (__cplusplus)
extern "C" {
#endif
/* Listener callbacks */
typedef void (*dds_on_inconsistent_topic_fn) (dds_entity_t topic, const dds_inconsistent_topic_status_t status, void* arg);
typedef void (*dds_on_liveliness_lost_fn) (dds_entity_t writer, const dds_liveliness_lost_status_t status, void* arg);
typedef void (*dds_on_offered_deadline_missed_fn) (dds_entity_t writer, const dds_offered_deadline_missed_status_t status, void* arg);
typedef void (*dds_on_offered_incompatible_qos_fn) (dds_entity_t writer, const dds_offered_incompatible_qos_status_t status, void* arg);
typedef void (*dds_on_data_on_readers_fn) (dds_entity_t subscriber, void* arg);
typedef void (*dds_on_sample_lost_fn) (dds_entity_t reader, const dds_sample_lost_status_t status, void* arg);
typedef void (*dds_on_data_available_fn) (dds_entity_t reader, void* arg);
typedef void (*dds_on_sample_rejected_fn) (dds_entity_t reader, const dds_sample_rejected_status_t status, void* arg);
typedef void (*dds_on_liveliness_changed_fn) (dds_entity_t reader, const dds_liveliness_changed_status_t status, void* arg);
typedef void (*dds_on_requested_deadline_missed_fn) (dds_entity_t reader, const dds_requested_deadline_missed_status_t status, void* arg);
typedef void (*dds_on_requested_incompatible_qos_fn) (dds_entity_t reader, const dds_requested_incompatible_qos_status_t status, void* arg);
typedef void (*dds_on_publication_matched_fn) (dds_entity_t writer, const dds_publication_matched_status_t status, void* arg);
typedef void (*dds_on_subscription_matched_fn) (dds_entity_t reader, const dds_subscription_matched_status_t status, void* arg);
#if 0
/* TODO: Why use (*dds_on_any_fn) (); and DDS_LUNSET? Why not just set the callbacks to NULL? */
typedef void (*dds_on_any_fn) (); /**< Empty parameter list on purpose; should be assignable without cast to all of the above. @todo check with an actual compiler; I'm a sloppy compiler */
#define DDS_LUNSET ((dds_on_any_fn)1) /**< Callback indicating a callback isn't set */
#else
#define DDS_LUNSET (NULL)
#endif
struct c_listener;
typedef struct c_listener dds_listener_t;
/**
* @brief Allocate memory and initializes to default values (::DDS_LUNSET) of a listener
*
* @param[in] arg optional pointer that will be passed on to the listener callbacks
*
* @return Returns a pointer to the allocated memory for dds_listener_t structure.
*/
_Ret_notnull_
DDS_EXPORT dds_listener_t* dds_listener_create (_In_opt_ void* arg);
/**
* @brief Delete the memory allocated to listener structure
*
* @param[in] listener pointer to the listener struct to delete
*/
DDS_EXPORT void dds_listener_delete (_In_ _Post_invalid_ dds_listener_t * __restrict listener);
/**
* @brief Reset the listener structure contents to ::DDS_LUNSET
*
* @param[in,out] listener pointer to the listener struct to reset
*/
DDS_EXPORT void dds_listener_reset (_Out_ dds_listener_t * __restrict listener);
/**
* @brief Copy the listener callbacks from source to destination
*
* @param[in,out] dst The pointer to the destination listener structure, where the content is to copied
* @param[in] src The pointer to the source listener structure to be copied
*/
DDS_EXPORT void dds_listener_copy (_Out_ dds_listener_t * __restrict dst, _In_ const dds_listener_t * __restrict src);
/**
* @brief Copy the listener callbacks from source to destination, unless already set
*
* Any listener callbacks already set in @p dst (including NULL) are skipped, only
* those set to DDS_LUNSET are copied from @p src.
*
* @param[in,out] dst The pointer to the destination listener structure, where the content is merged
* @param[in] src The pointer to the source listener structure to be copied
*/
DDS_EXPORT void dds_listener_merge (_Inout_ dds_listener_t * __restrict dst, _In_ const dds_listener_t * __restrict src);
/************************************************************************************************
* Setters
************************************************************************************************/
/**
* @brief Set the inconsistent_topic callback in the listener structure.
*
* @param listener The pointer to the listener structure, where the callback will be set
* @param callback The callback to set in the listener, can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lset_inconsistent_topic (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_inconsistent_topic_fn callback);
/**
* @brief Set the liveliness_lost callback in the listener structure.
*
* @param[out] listener The pointer to the listener structure, where the callback will be set
* @param[in] callback The callback to set in the listener, can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lset_liveliness_lost (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_liveliness_lost_fn callback);
/**
* @brief Set the offered_deadline_missed callback in the listener structure.
*
* @param[in,out] listener The pointer to the listener structure, where the callback will be set
* @param[in] callback The callback to set in the listener, can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lset_offered_deadline_missed (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_offered_deadline_missed_fn callback);
/**
* @brief Set the offered_incompatible_qos callback in the listener structure.
*
* @param[in,out] listener The pointer to the listener structure, where the callback will be set
* @param[in] callback The callback to set in the listener, can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lset_offered_incompatible_qos (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_offered_incompatible_qos_fn callback);
/**
* @brief Set the data_on_readers callback in the listener structure.
*
* @param[in,out] listener The pointer to the listener structure, where the callback will be set
* @param[in] callback The callback to set in the listener, can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lset_data_on_readers (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_data_on_readers_fn callback);
/**
* @brief Set the sample_lost callback in the listener structure.
*
* @param[in,out] listener The pointer to the listener structure, where the callback will be set
* @param[in] callback The callback to set in the listener, can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lset_sample_lost (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_sample_lost_fn callback);
/**
* @brief Set the data_available callback in the listener structure.
*
* @param[in,out] listener The pointer to the listener structure, where the callback will be set
* @param[in] callback The callback to set in the listener, can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lset_data_available (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_data_available_fn callback);
/**
* @brief Set the sample_rejected callback in the listener structure.
*
* @param[in,out] listener The pointer to the listener structure, where the callback will be set
* @param[in] callback The callback to set in the listener, can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lset_sample_rejected (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_sample_rejected_fn callback);
/**
* @brief Set the liveliness_changed callback in the listener structure.
*
* @param[in,out] listener The pointer to the listener structure, where the callback will be set
* @param[in] callback The callback to set in the listener, can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lset_liveliness_changed (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_liveliness_changed_fn callback);
/**
* @brief Set the requested_deadline_missed callback in the listener structure.
*
* @param[in,out] listener The pointer to the listener structure, where the callback will be set
* @param[in] callback The callback to set in the listener, can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lset_requested_deadline_missed (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_requested_deadline_missed_fn callback);
/**
* @brief Set the requested_incompatible_qos callback in the listener structure.
*
* @param[in,out] listener The pointer to the listener structure, where the callback will be set
* @param[in] callback The callback to set in the listener, can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lset_requested_incompatible_qos (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_requested_incompatible_qos_fn callback);
/**
* @brief Set the publication_matched callback in the listener structure.
*
* @param[in,out] listener The pointer to the listener structure, where the callback will be set
* @param[in] callback The callback to set in the listener, can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lset_publication_matched (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_publication_matched_fn callback);
/**
* @brief Set the subscription_matched callback in the listener structure.
*
* @param[in,out] listener The pointer to the listener structure, where the callback will be set
* @param[in] callback The callback to set in the listener, can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lset_subscription_matched (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_subscription_matched_fn callback);
/************************************************************************************************
* Getters
************************************************************************************************/
/**
* @brief Get the inconsistent_topic callback from the listener structure.
*
* @param[in] listener The pointer to the listener structure, where the callback will be retrieved from
* @param[in,out] callback Pointer where the retrieved callback can be stored; can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lget_inconsistent_topic (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_inconsistent_topic_fn *callback);
/**
* @brief Get the liveliness_lost callback from the listener structure.
*
* @param[in] listener The pointer to the listener structure, where the callback will be retrieved from
* @param[in,out] callback Pointer where the retrieved callback can be stored; can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lget_liveliness_lost (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_liveliness_lost_fn *callback);
/**
* @brief Get the offered_deadline_missed callback from the listener structure.
*
* @param[in] listener The pointer to the listener structure, where the callback will be retrieved from
* @param[in,out] callback Pointer where the retrieved callback can be stored; can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lget_offered_deadline_missed (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_offered_deadline_missed_fn *callback);
/**
* @brief Get the offered_incompatible_qos callback from the listener structure.
*
* @param[in] listener The pointer to the listener structure, where the callback will be retrieved from
* @param[in,out] callback Pointer where the retrieved callback can be stored; can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lget_offered_incompatible_qos (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_offered_incompatible_qos_fn *callback);
/**
* @brief Get the data_on_readers callback from the listener structure.
*
* @param[in] listener The pointer to the listener structure, where the callback will be retrieved from
* @param[in,out] callback Pointer where the retrieved callback can be stored; can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lget_data_on_readers (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_data_on_readers_fn *callback);
/**
* @brief Get the sample_lost callback from the listener structure.
*
* @param[in] listener The pointer to the listener structure, where the callback will be retrieved from
* @param[in,out] callback Pointer where the retrieved callback can be stored; can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lget_sample_lost (_In_ const dds_listener_t *__restrict listener, _Outptr_result_maybenull_ dds_on_sample_lost_fn *callback);
/**
* @brief Get the data_available callback from the listener structure.
*
* @param[in] listener The pointer to the listener structure, where the callback will be retrieved from
* @param[in,out] callback Pointer where the retrieved callback can be stored; can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lget_data_available (_In_ const dds_listener_t *__restrict listener, _Outptr_result_maybenull_ dds_on_data_available_fn *callback);
/**
* @brief Get the sample_rejected callback from the listener structure.
*
* @param[in] listener The pointer to the listener structure, where the callback will be retrieved from
* @param[in,out] callback Pointer where the retrieved callback can be stored; can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lget_sample_rejected (_In_ const dds_listener_t *__restrict listener, _Outptr_result_maybenull_ dds_on_sample_rejected_fn *callback);
/**
* @brief Get the liveliness_changed callback from the listener structure.
*
* @param[in] listener The pointer to the listener structure, where the callback will be retrieved from
* @param[in,out] callback Pointer where the retrieved callback can be stored; can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lget_liveliness_changed (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_liveliness_changed_fn *callback);
/**
* @brief Get the requested_deadline_missed callback from the listener structure.
*
* @param[in] listener The pointer to the listener structure, where the callback will be retrieved from
* @param[in,out] callback Pointer where the retrieved callback can be stored; can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lget_requested_deadline_missed (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_requested_deadline_missed_fn *callback);
/**
* @brief Get the requested_incompatible_qos callback from the listener structure.
*
* @param[in] listener The pointer to the listener structure, where the callback will be retrieved from
* @param[in,out] callback Pointer where the retrieved callback can be stored; can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lget_requested_incompatible_qos (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_requested_incompatible_qos_fn *callback);
/**
* @brief Get the publication_matched callback from the listener structure.
*
* @param[in] listener The pointer to the listener structure, where the callback will be retrieved from
* @param[in,out] callback Pointer where the retrieved callback can be stored; can be NULL, ::DDS_LUNSET or a valid callback pointer
*/
DDS_EXPORT void dds_lget_publication_matched (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_publication_matched_fn *callback);
/**
* @brief Get the subscription_matched callback from the listener structure.
*
* @param[in] callback Pointer where the retrieved callback can be stored; can be NULL, ::DDS_LUNSET or a valid callback pointer
* @param[in,out] listener The pointer to the listener structure, where the callback will be retrieved from
*/
DDS_EXPORT void dds_lget_subscription_matched (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_subscription_matched_fn *callback);
#if defined (__cplusplus)
}
#endif
#endif /*_DDS_PUBLIC_LISTENER_H_*/

View file

@ -0,0 +1,39 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
/* TODO: do we really need to expose this as an API? */
/** @file
*
* @brief DDS C Logging API
*
* This header file defines the public API for logging in the
* CycloneDDS C language binding.
*/
#ifndef DDS_LOG_H
#define DDS_LOG_H
#include "os/os_public.h"
#include "ddsc/dds_export.h"
#if defined (__cplusplus)
extern "C" {
#endif
DDS_EXPORT void dds_log_info (const char * fmt, ...);
DDS_EXPORT void dds_log_warn (const char * fmt, ...);
DDS_EXPORT void dds_log_error (const char * fmt, ...);
DDS_EXPORT void dds_log_fatal (const char * fmt, ...);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,815 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
/** @file
*
* @brief DDS C QoS API
*
* This header file defines the public API of QoS and Policies in the
* CycloneDDS C language binding.
*/
#ifndef DDS_QOS_H
#define DDS_QOS_H
#include "os/os_public.h"
#include "ddsc/dds_export.h"
#if defined (__cplusplus)
extern "C" {
#endif
/* QoS identifiers */
/** @name QoS identifiers
@{**/
#define DDS_INVALID_QOS_POLICY_ID 0
#define DDS_USERDATA_QOS_POLICY_ID 1
#define DDS_DURABILITY_QOS_POLICY_ID 2
#define DDS_PRESENTATION_QOS_POLICY_ID 3
#define DDS_DEADLINE_QOS_POLICY_ID 4
#define DDS_LATENCYBUDGET_QOS_POLICY_ID 5
#define DDS_OWNERSHIP_QOS_POLICY_ID 6
#define DDS_OWNERSHIPSTRENGTH_QOS_POLICY_ID 7
#define DDS_LIVELINESS_QOS_POLICY_ID 8
#define DDS_TIMEBASEDFILTER_QOS_POLICY_ID 9
#define DDS_PARTITION_QOS_POLICY_ID 10
#define DDS_RELIABILITY_QOS_POLICY_ID 11
#define DDS_DESTINATIONORDER_QOS_POLICY_ID 12
#define DDS_HISTORY_QOS_POLICY_ID 13
#define DDS_RESOURCELIMITS_QOS_POLICY_ID 14
#define DDS_ENTITYFACTORY_QOS_POLICY_ID 15
#define DDS_WRITERDATALIFECYCLE_QOS_POLICY_ID 16
#define DDS_READERDATALIFECYCLE_QOS_POLICY_ID 17
#define DDS_TOPICDATA_QOS_POLICY_ID 18
#define DDS_GROUPDATA_QOS_POLICY_ID 19
#define DDS_TRANSPORTPRIORITY_QOS_POLICY_ID 20
#define DDS_LIFESPAN_QOS_POLICY_ID 21
#define DDS_DURABILITYSERVICE_QOS_POLICY_ID 22
/** @}*/
/* QoS structure is opaque */
/** QoS structure */
typedef struct nn_xqos dds_qos_t;
/** Durability QoS: Applies to Topic, DataReader, DataWriter */
typedef enum dds_durability_kind
{
DDS_DURABILITY_VOLATILE,
DDS_DURABILITY_TRANSIENT_LOCAL,
DDS_DURABILITY_TRANSIENT,
DDS_DURABILITY_PERSISTENT
}
dds_durability_kind_t;
/** History QoS: Applies to Topic, DataReader, DataWriter */
typedef enum dds_history_kind
{
DDS_HISTORY_KEEP_LAST,
DDS_HISTORY_KEEP_ALL
}
dds_history_kind_t;
/** Ownership QoS: Applies to Topic, DataReader, DataWriter */
typedef enum dds_ownership_kind
{
DDS_OWNERSHIP_SHARED,
DDS_OWNERSHIP_EXCLUSIVE
}
dds_ownership_kind_t;
/** Liveliness QoS: Applies to Topic, DataReader, DataWriter */
typedef enum dds_liveliness_kind
{
DDS_LIVELINESS_AUTOMATIC,
DDS_LIVELINESS_MANUAL_BY_PARTICIPANT,
DDS_LIVELINESS_MANUAL_BY_TOPIC
}
dds_liveliness_kind_t;
/** Reliability QoS: Applies to Topic, DataReader, DataWriter */
typedef enum dds_reliability_kind
{
DDS_RELIABILITY_BEST_EFFORT,
DDS_RELIABILITY_RELIABLE
}
dds_reliability_kind_t;
/** DestinationOrder QoS: Applies to Topic, DataReader, DataWriter */
typedef enum dds_destination_order_kind
{
DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP,
DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP
}
dds_destination_order_kind_t;
/** History QoS: Applies to Topic, DataReader, DataWriter */
typedef struct dds_history_qospolicy
{
dds_history_kind_t kind;
int32_t depth;
}
dds_history_qospolicy_t;
/** ResourceLimits QoS: Applies to Topic, DataReader, DataWriter */
typedef struct dds_resource_limits_qospolicy
{
int32_t max_samples;
int32_t max_instances;
int32_t max_samples_per_instance;
}
dds_resource_limits_qospolicy_t;
/** Presentation QoS: Applies to Publisher, Subscriber */
typedef enum dds_presentation_access_scope_kind
{
DDS_PRESENTATION_INSTANCE,
DDS_PRESENTATION_TOPIC,
DDS_PRESENTATION_GROUP
}
dds_presentation_access_scope_kind_t;
/**
* @brief Allocate memory and initialize default QoS-policies
*
* @returns - Pointer to the initialized dds_qos_t structure, NULL if unsuccessful.
*/
_Ret_notnull_
DDS_EXPORT
dds_qos_t * dds_qos_create (void);
/**
* @brief Delete memory allocated to QoS-policies structure
*
* @param[in] qos - Pointer to dds_qos_t structure
*/
DDS_EXPORT
void dds_qos_delete (
_In_ _Post_invalid_ dds_qos_t * __restrict qos
);
/**
* @brief Reset a QoS-policies structure to default values
*
* @param[in,out] qos - Pointer to the dds_qos_t structure
*/
DDS_EXPORT
void dds_qos_reset (
_Out_ dds_qos_t * __restrict qos
);
/**
* @brief Copy all QoS-policies from one structure to another
*
* @param[in,out] dst - Pointer to the destination dds_qos_t structure
* @param[in] src - Pointer to the source dds_qos_t structure
*
* @returns - Return-code indicating success or failure
*/
DDS_EXPORT
dds_return_t dds_qos_copy (
_Out_ dds_qos_t * __restrict dst,
_In_ const dds_qos_t * __restrict src
);
/**
* @brief Copy all QoS-policies from one structure to another, unless already set
*
* Policies are copied from src to dst, unless src already has the policy set to a non-default value.
*
* @param[in,out] dst - Pointer to the destination qos structure
* @param[in] src - Pointer to the source qos structure
*/
DDS_EXPORT
void dds_qos_merge
(
_Inout_ dds_qos_t * __restrict dst,
_In_ const dds_qos_t * __restrict src
);
/**
* @brief Set the userdata of a qos structure.
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the userdata
* @param[in] value - Pointer to the userdata
* @param[in] sz - Size of userdata stored in value
*/
DDS_EXPORT
void dds_qset_userdata
(
_Inout_ dds_qos_t * __restrict qos,
_In_reads_bytes_opt_(sz) const void * __restrict value,
_In_ size_t sz
);
/**
* @brief Set the topicdata of a qos structure.
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the topicdata
* @param[in] value - Pointer to the topicdata
* @param[in] sz - Size of the topicdata stored in value
*/
DDS_EXPORT
void dds_qset_topicdata
(
_Inout_ dds_qos_t * __restrict qos,
_In_reads_bytes_opt_(sz) const void * __restrict value,
_In_ size_t sz
);
/**
* @brief Set the groupdata of a qos structure.
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the groupdata
* @param[in] value - Pointer to the group data
* @param[in] sz - Size of groupdata stored in value
*/
DDS_EXPORT
void dds_qset_groupdata
(
_Inout_ dds_qos_t * __restrict qos,
_In_reads_bytes_opt_(sz) const void * __restrict value,
_In_ size_t sz
);
/**
* @brief Set the durability policy of a qos structure.
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* @param[in] kind - Durability kind value \ref DCPS_QoS_Durability
*/
DDS_EXPORT
void dds_qset_durability
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(DDS_DURABILITY_VOLATILE, DDS_DURABILITY_PERSISTENT) dds_durability_kind_t kind
);
/**
* @brief Set the history policy of a qos structure.
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* @param[in] kind - History kind value \ref DCPS_QoS_History
* @param[in] depth - History depth value \ref DCPS_QoS_History
*/
DDS_EXPORT
void dds_qset_history
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(DDS_HISTORY_KEEP_LAST, DDS_HISTORY_KEEP_ALL) dds_history_kind_t kind,
_In_range_(>=, DDS_LENGTH_UNLIMITED) int32_t depth
);
/**
* @brief Set the resource limits policy of a qos structure.
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* @param[in] max_samples - Number of samples resource-limit value
* @param[in] max_instances - Number of instances resource-limit value
* @param[in] max_samples_per_instance - Number of samples per instance resource-limit value
*/
DDS_EXPORT
void dds_qset_resource_limits
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(>=, DDS_LENGTH_UNLIMITED) int32_t max_samples,
_In_range_(>=, DDS_LENGTH_UNLIMITED) int32_t max_instances,
_In_range_(>=, DDS_LENGTH_UNLIMITED) int32_t max_samples_per_instance
);
/**
* @brief Set the presentation policy of a qos structure.
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* @param[in] access_scope - Access-scope kind
* @param[in] coherent_access - Coherent access enable value
* @param[in] ordered_access - Ordered access enable value
*/
DDS_EXPORT void dds_qset_presentation
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(DDS_PRESENTATION_INSTANCE, DDS_PRESENTATION_GROUP) dds_presentation_access_scope_kind_t access_scope,
_In_ bool coherent_access,
_In_ bool ordered_access
);
/**
* @brief Set the lifespan policy of a qos structure.
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* @param[in] lifespan - Lifespan duration (expiration time relative to source timestamp of a sample)
*/
DDS_EXPORT
void dds_qset_lifespan
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(0, DDS_INFINITY) dds_duration_t lifespan
);
/**
* @brief Set the deadline policy of a qos structure.
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* @param[in] deadline - Deadline duration
*/
DDS_EXPORT
void dds_qset_deadline
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(0, DDS_INFINITY) dds_duration_t deadline
);
/**
* @brief Set the latency-budget policy of a qos structure
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* @param[in] duration - Latency budget duration
*/
DDS_EXPORT
void dds_qset_latency_budget
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(0, DDS_INFINITY) dds_duration_t duration
);
/**
* @brief Set the ownership policy of a qos structure
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* @param[in] kind - Ownership kind
*/
DDS_EXPORT
void dds_qset_ownership
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(DDS_OWNERSHIP_SHARED, DDS_OWNERSHIP_EXCLUSIVE) dds_ownership_kind_t kind
);
/**
* @brief Set the ownership strength policy of a qos structure
*
* param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* param[in] value - Ownership strength value
*/
DDS_EXPORT
void dds_qset_ownership_strength
(
_Inout_ dds_qos_t * __restrict qos,
_In_ int32_t value
);
/**
* @brief Set the liveliness policy of a qos structure
*
* param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* param[in] kind - Liveliness kind
* param[in[ lease_duration - Lease duration
*/
DDS_EXPORT
void dds_qset_liveliness
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(DDS_LIVELINESS_AUTOMATIC, DDS_LIVELINESS_MANUAL_BY_TOPIC) dds_liveliness_kind_t kind,
_In_range_(0, DDS_INFINITY) dds_duration_t lease_duration
);
/**
* @brief Set the time-based filter policy of a qos structure
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* @param[in] minimum_separation - Minimum duration between sample delivery for an instance
*/
DDS_EXPORT
void dds_qset_time_based_filter
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(0, DDS_INFINITY) dds_duration_t minimum_separation
);
/**
* @brief Set the partition policy of a qos structure
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* @param[in] n - Number of partitions stored in ps
* @param[in[ ps - Pointer to string(s) storing partition name(s)
*/
DDS_EXPORT
void dds_qset_partition
(
_Inout_ dds_qos_t * __restrict qos,
_In_ uint32_t n,
_In_count_(n) _Deref_pre_z_ const char ** __restrict ps
);
/**
* @brief Set the reliability policy of a qos structure
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* @param[in] kind - Reliability kind
* @param[in] max_blocking_time - Max blocking duration applied when kind is reliable.
*/
DDS_EXPORT
void dds_qset_reliability
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(DDS_RELIABILITY_BEST_EFFORT, DDS_RELIABILITY_RELIABLE) dds_reliability_kind_t kind,
_In_range_(0, DDS_INFINITY) dds_duration_t max_blocking_time
);
/**
* @brief Set the transport-priority policy of a qos structure
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* @param[in] value - Priority value
*/
DDS_EXPORT
void dds_qset_transport_priority
(
_Inout_ dds_qos_t * __restrict qos,
_In_ int32_t value
);
/**
* @brief Set the destination-order policy of a qos structure
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* @param[in] kind - Destination-order kind
*/
DDS_EXPORT
void dds_qset_destination_order
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP,
DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP) dds_destination_order_kind_t kind
);
/**
* @brief Set the writer data-lifecycle policy of a qos structure
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* @param[in] autodispose_unregistered_instances - Automatic disposal of unregistered instances
*/
DDS_EXPORT
void dds_qset_writer_data_lifecycle
(
_Inout_ dds_qos_t * __restrict qos,
_In_ bool autodispose
);
/**
* @brief Set the reader data-lifecycle policy of a qos structure
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* @param[in] autopurge_nowriter_samples_delay - Delay for purging of samples from instances in a no-writers state
* @param[in] autopurge_disposed_samples_delay - Delay for purging of samples from disposed instances
*/
DDS_EXPORT
void dds_qset_reader_data_lifecycle
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(0, DDS_INFINITY) dds_duration_t autopurge_nowriter_samples_delay,
_In_range_(0, DDS_INFINITY) dds_duration_t autopurge_disposed_samples_delay
);
/**
* @brief Set the durability-service policy of a qos structure
*
* @param[in,out] qos - Pointer to a dds_qos_t structure that will store the policy
* @param[in] service_cleanup_delay - Delay for purging of abandoned instances from the durability service
* @param[in] history_kind - History policy kind applied by the durability service
* @param[in] history_depth - History policy depth applied by the durability service
* @param[in] max_samples - Number of samples resource-limit policy applied by the durability service
* @param[in] max_instances - Number of instances resource-limit policy applied by the durability service
* @param[in] max_samples_per_instance - Number of samples per instance resource-limit policy applied by the durability service
*/
DDS_EXPORT
void dds_qset_durability_service
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(0, DDS_INFINITY) dds_duration_t service_cleanup_delay,
_In_range_(DDS_HISTORY_KEEP_LAST, DDS_HISTORY_KEEP_ALL) dds_history_kind_t history_kind,
_In_range_(>=, DDS_LENGTH_UNLIMITED) int32_t history_depth,
_In_range_(>=, DDS_LENGTH_UNLIMITED) int32_t max_samples,
_In_range_(>=, DDS_LENGTH_UNLIMITED) int32_t max_instances,
_In_range_(>=, DDS_LENGTH_UNLIMITED) int32_t max_samples_per_instance
);
/**
* @brief Get the userdata from a qos structure
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] value - Pointer that will store the userdata
* @param[in,out] sz - Pointer that will store the size of userdata
*/
DDS_EXPORT
void dds_qget_userdata
(
_In_ const dds_qos_t * __restrict qos,
_Outptr_result_bytebuffer_maybenull_(*sz) void ** value,
_Out_ size_t * sz
);
/**
* @brief Get the topicdata from a qos structure
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] value - Pointer that will store the topicdata
* @param[in,out] sz - Pointer that will store the size of topicdata
*/
DDS_EXPORT
void dds_qget_topicdata
(
_In_ const dds_qos_t * __restrict qos,
_Outptr_result_bytebuffer_maybenull_(*sz) void ** value,
_Out_ size_t * sz
);
/**
* @brief Get the groupdata from a qos structure
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] value - Pointer that will store the groupdata
* @param[in,out] sz - Pointer that will store the size of groupdata
*/
DDS_EXPORT
void dds_qget_groupdata
(
_In_ const dds_qos_t * __restrict qos,
_Outptr_result_bytebuffer_maybenull_(*sz) void ** value,
_Out_ size_t * sz
);
/**
* @brief Get the durability policy from a qos structure
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] kind - Pointer that will store the durability kind
*/
DDS_EXPORT
void dds_qget_durability
(
_In_ const dds_qos_t * __restrict qos,
_Out_ dds_durability_kind_t *kind
);
/**
* @brief Get the history policy from a qos structure
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] kind - Pointer that will store the history kind (optional)
* @param[in,out] depth - Pointer that will store the history depth (optional)
*/
DDS_EXPORT
void dds_qget_history
(
_In_ const dds_qos_t * __restrict qos,
_Out_opt_ dds_history_kind_t * kind,
_Out_opt_ int32_t *depth
);
/**
* @brief Get the resource-limits policy from a qos structure
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] max_samples - Pointer that will store the number of samples resource-limit (optional)
* @param[in,out] max_instances - Pointer that will store the number of instances resource-limit (optional)
* @param[in,out] max_samples_per_instance - Pointer that will store the number of samples per instance resource-limit (optional)
*/
DDS_EXPORT
void dds_qget_resource_limits
(
_In_ const dds_qos_t * __restrict qos,
_Out_opt_ int32_t *max_samples,
_Out_opt_ int32_t *max_instances,
_Out_opt_ int32_t *max_samples_per_instance
);
/**
* @brief Get the presentation policy from a qos structure
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] access_scope - Pointer that will store access scope kind (optional)
* @param[in,out] coherent_access - Pointer that will store coherent access enable value (optional)
* @param[in,out] ordered_access - Pointer that will store orderede access enable value (optional)
*/
DDS_EXPORT
void dds_qget_presentation
(
_In_ const dds_qos_t * __restrict qos,
_Out_opt_ dds_presentation_access_scope_kind_t *access_scope,
_Out_opt_ bool *coherent_access,
_Out_opt_ bool *ordered_access
);
/**
* @brief Get the lifespan policy from a qos structure
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] lifespan - Pointer that will store lifespan duration
*/
DDS_EXPORT
void dds_qget_lifespan
(
_In_ const dds_qos_t * __restrict qos,
_Out_ dds_duration_t * lifespan
);
/**
* @brief Get the deadline policy from a qos structure
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] deadline - Pointer that will store deadline duration
*/
DDS_EXPORT
void dds_qget_deadline
(
_In_ const dds_qos_t * __restrict qos,
_Out_ dds_duration_t * deadline
);
/**
* @brief Get the latency-budget policy from a qos structure
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] duration - Pointer that will store latency-budget duration
*/
DDS_EXPORT
void dds_qget_latency_budget
(
_In_ const dds_qos_t * __restrict qos,
_Out_ dds_duration_t *duration
);
/**
* @brief Get the ownership policy from a qos structure
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] kind - Pointer that will store the ownership kind
*/
DDS_EXPORT
void dds_qget_ownership
(
_In_ const dds_qos_t * __restrict qos,
_Out_ dds_ownership_kind_t *kind
);
/**
* @brief Get the ownership strength qos policy
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] value - Pointer that will store the ownership strength value
*/
DDS_EXPORT
void dds_qget_ownership_strength
(
_In_ const dds_qos_t * __restrict qos,
_Out_ int32_t *value
);
/**
* @brief Get the liveliness qos policy
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] kind - Pointer that will store the liveliness kind (optional)
* @param[in,out] lease_duration - Pointer that will store the liveliness lease duration (optional)
*/
DDS_EXPORT
void dds_qget_liveliness
(
_In_ const dds_qos_t * __restrict qos,
_Out_opt_ dds_liveliness_kind_t *kind,
_Out_opt_ dds_duration_t *lease_duration
);
/**
* @brief Get the time-based filter qos policy
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] minimum_separation - Pointer that will store the minimum separation duration (optional)
*/
DDS_EXPORT
void dds_qget_time_based_filter
(
_In_ const dds_qos_t * __restrict qos,
_Out_ dds_duration_t *minimum_separation
);
/**
* @brief Get the partition qos policy
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] n - Pointer that will store the number of partitions (optional)
* @param[in,out] ps - Pointer that will store the string(s) containing partition name(s) (optional)
*/
DDS_EXPORT
void dds_qget_partition
(
_In_ const dds_qos_t * __restrict qos,
_Out_ uint32_t *n,
_Outptr_opt_result_buffer_all_maybenull_(*n) char *** ps
);
/**
* @brief Get the reliability qos policy
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] kind - Pointer that will store the reliability kind (optional)
* @param[in,out] max_blocking_time - Pointer that will store the max blocking time for reliable reliability (optional)
*/
DDS_EXPORT
void dds_qget_reliability
(
_In_ const dds_qos_t * __restrict qos,
_Out_opt_ dds_reliability_kind_t *kind,
_Out_opt_ dds_duration_t *max_blocking_time
);
/**
* @brief Get the transport priority qos policy
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] value - Pointer that will store the transport priority value
*/
DDS_EXPORT
void dds_qget_transport_priority
(
_In_ const dds_qos_t * __restrict qos,
_Out_ int32_t *value
);
/**
* @brief Get the destination-order qos policy
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] kind - Pointer that will store the destination-order kind
*/
DDS_EXPORT
void dds_qget_destination_order
(
_In_ const dds_qos_t * __restrict qos,
_Out_ dds_destination_order_kind_t *kind
);
/**
* @brief Get the writer data-lifecycle qos policy
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] autodispose_unregistered_instances - Pointer that will store the autodispose unregistered instances enable value
*/
DDS_EXPORT
void dds_qget_writer_data_lifecycle
(
_In_ const dds_qos_t * __restrict qos,
_Out_ bool * autodispose
);
/**
* @brief Get the reader data-lifecycle qos policy
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] autopurge_nowriter_samples_delay - Pointer that will store the delay for auto-purging samples from instances in a no-writer state (optional)
* @param[in,out] autopurge_disposed_samples_delay - Pointer that will store the delay for auto-purging of disposed instances (optional)
*/
DDS_EXPORT
void dds_qget_reader_data_lifecycle
(
_In_ const dds_qos_t * __restrict qos,
_Out_opt_ dds_duration_t *autopurge_nowriter_samples_delay,
_Out_opt_ dds_duration_t *autopurge_disposed_samples_delay
);
/**
* @brief Get the durability-service qos policy values.
*
* @param[in] qos - Pointer to a dds_qos_t structure storing the policy
* @param[in,out] service_cleanup_delay - Pointer that will store the delay for purging of abandoned instances from the durability service (optional)
* @param[in,out] history_kind - Pointer that will store history policy kind applied by the durability service (optional)
* @param[in,out] history_depth - Pointer that will store history policy depth applied by the durability service (optional)
* @param[in,out] max_samples - Pointer that will store number of samples resource-limit policy applied by the durability service (optional)
* @param[in,out] max_instances - Pointer that will store number of instances resource-limit policy applied by the durability service (optional)
* @param[in,out] max_samples_per_instance - Pointer that will store number of samples per instance resource-limit policy applied by the durability service (optional)
*/
DDS_EXPORT void dds_qget_durability_service
(
_In_ const dds_qos_t * qos,
_Out_opt_ dds_duration_t * service_cleanup_delay,
_Out_opt_ dds_history_kind_t * history_kind,
_Out_opt_ int32_t * history_depth,
_Out_opt_ int32_t * max_samples,
_Out_opt_ int32_t * max_instances,
_Out_opt_ int32_t * max_samples_per_instance
);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,491 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
/** @file
*
* @brief DDS C Communication Status API
*
* This header file defines the public API of the Communication Status in the
* CycloneDDS C language binding.
*/
#ifndef DDS_STATUS_H
#define DDS_STATUS_H
#include "os/os_public.h"
#include "ddsc/dds_export.h"
#if defined (__cplusplus)
extern "C" {
#endif
/*
Listeners implemented as structs containing callback functions
that take listener status types as arguments.
*/
/* Listener status types */
/**
* \ref DCPS_Status_OfferedDeadlineMissed
*/
typedef struct dds_offered_deadline_missed_status
{
uint32_t total_count;
int32_t total_count_change;
dds_instance_handle_t last_instance_handle;
}
dds_offered_deadline_missed_status_t;
/**
* \ref DCPS_Status_OfferedIncompatibleQoS
*/
typedef struct dds_offered_incompatible_qos_status
{
uint32_t total_count;
int32_t total_count_change;
uint32_t last_policy_id;
}
dds_offered_incompatible_qos_status_t;
/**
* \ref DCPS_Status_PublicationMatched
*/
typedef struct dds_publication_matched_status
{
uint32_t total_count;
int32_t total_count_change;
uint32_t current_count;
int32_t current_count_change;
dds_instance_handle_t last_subscription_handle;
}
dds_publication_matched_status_t;
/**
* \ref DCPS_Status_LivelinessLost
*/
typedef struct dds_liveliness_lost_status
{
uint32_t total_count;
int32_t total_count_change;
}
dds_liveliness_lost_status_t;
/**
* \ref DCPS_Status_SubscriptionMatched
*/
typedef struct dds_subscription_matched_status
{
uint32_t total_count;
int32_t total_count_change;
uint32_t current_count;
int32_t current_count_change;
dds_instance_handle_t last_publication_handle;
}
dds_subscription_matched_status_t;
/**
* dds_sample_rejected_status_kind
*/
typedef enum
{
DDS_NOT_REJECTED,
DDS_REJECTED_BY_INSTANCES_LIMIT,
DDS_REJECTED_BY_SAMPLES_LIMIT,
DDS_REJECTED_BY_SAMPLES_PER_INSTANCE_LIMIT
}
dds_sample_rejected_status_kind;
/**
* \ref DCPS_Status_SampleRejected
*/
typedef struct dds_sample_rejected_status
{
uint32_t total_count;
int32_t total_count_change;
dds_sample_rejected_status_kind last_reason;
dds_instance_handle_t last_instance_handle;
}
dds_sample_rejected_status_t;
/**
* \ref DCPS_Status_LivelinessChanged
*/
typedef struct dds_liveliness_changed_status
{
uint32_t alive_count;
uint32_t not_alive_count;
int32_t alive_count_change;
int32_t not_alive_count_change;
dds_instance_handle_t last_publication_handle;
}
dds_liveliness_changed_status_t;
/**
* \ref DCPS_Status_RequestedDeadlineMissed
*/
typedef struct dds_requested_deadline_missed_status
{
uint32_t total_count;
int32_t total_count_change;
dds_instance_handle_t last_instance_handle;
}
dds_requested_deadline_missed_status_t;
/**
* \ref DCPS_Status_RequestedIncompatibleQoS
*/
typedef struct dds_requested_incompatible_qos_status
{
uint32_t total_count;
int32_t total_count_change;
uint32_t last_policy_id;
}
dds_requested_incompatible_qos_status_t;
/**
* \ref DCPS_Status_SampleLost
*/
typedef struct dds_sample_lost_status
{
uint32_t total_count;
int32_t total_count_change;
}
dds_sample_lost_status_t;
/**
* \ref DCPS_Status_InconsistentTopic
*/
typedef struct dds_inconsistent_topic_status
{
uint32_t total_count;
int32_t total_count_change;
}
dds_inconsistent_topic_status_t;
/*
get_<status> APIs return the status of an entity and resets the status
*/
/**
* @brief Get INCONSISTENT_TOPIC status
*
* This operation gets the status value corresponding to INCONSISTENT_TOPIC
* and reset the status. The value can be obtained, only if the status is enabled for an entity.
* NULL value for status is allowed and it will reset the trigger value when status is enabled.
*
* @param[in] topic The entity to get the status
* @param[out] status The pointer to \ref DCPS_Status_InconsistentTopic to get the status
*
* @returns 0 - Success
* @returns <0 - Failure (use dds_err_nr() to get error value).
*
* @retval DDS_RETCODE_ERROR
* An internal error has occurred.
* @retval DDS_RETCODE_BAD_PARAMETER
* One of the given arguments is not valid.
* @retval DDS_RETCODE_ILLEGAL_OPERATION
* The operation is invoked on an inappropriate object.
* @retval DDS_RETCODE_ALREADY_DELETED
* The entity has already been deleted.
*/
_Pre_satisfies_((topic & DDS_ENTITY_KIND_MASK) == DDS_KIND_TOPIC)
DDS_EXPORT dds_return_t
dds_get_inconsistent_topic_status (
_In_ dds_entity_t topic,
_Out_opt_ dds_inconsistent_topic_status_t * status);
/**
* @brief Get PUBLICATION_MATCHED status
*
* This operation gets the status value corresponding to PUBLICATION_MATCHED
* and reset the status. The value can be obtained, only if the status is enabled for an entity.
* NULL value for status is allowed and it will reset the trigger value when status is enabled.
*
* @param[in] writer The entity to get the status
* @param[out] status The pointer to \ref DCPS_Status_PublicationMatched to get the status
*
* @returns 0 - Success
* @returns <0 - Failure (use dds_err_nr() to get error value).
*
* @retval DDS_RETCODE_ERROR
* An internal error has occurred.
* @retval DDS_RETCODE_BAD_PARAMETER
* One of the given arguments is not valid.
* @retval DDS_RETCODE_ILLEGAL_OPERATION
* The operation is invoked on an inappropriate object.
* @retval DDS_RETCODE_ALREADY_DELETED
* The entity has already been deleted.
*/
_Pre_satisfies_(((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER))
DDS_EXPORT dds_return_t
dds_get_publication_matched_status (
_In_ dds_entity_t writer,
_Out_opt_ dds_publication_matched_status_t * status);
/**
* @brief Get LIVELINESS_LOST status
*
* This operation gets the status value corresponding to LIVELINESS_LOST
* and reset the status. The value can be obtained, only if the status is enabled for an entity.
* NULL value for status is allowed and it will reset the trigger value when status is enabled.
*
* @param[in] writer The entity to get the status
* @param[out] status The pointer to \ref DCPS_Status_LivelinessLost to get the status
*
* @returns 0 - Success
* @returns <0 - Failure (use dds_err_nr() to get error value).
*
* @retval DDS_RETCODE_ERROR
* An internal error has occurred.
* @retval DDS_RETCODE_BAD_PARAMETER
* One of the given arguments is not valid.
* @retval DDS_RETCODE_ILLEGAL_OPERATION
* The operation is invoked on an inappropriate object.
* @retval DDS_RETCODE_ALREADY_DELETED
* The entity has already been deleted.
*/
_Pre_satisfies_(((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER))
DDS_EXPORT dds_return_t dds_get_liveliness_lost_status (
_In_ dds_entity_t writer,
_Out_opt_ dds_liveliness_lost_status_t * status);
/**
* @brief Get OFFERED_DEADLINE_MISSED status
*
* This operation gets the status value corresponding to OFFERED_DEADLINE_MISSED
* and reset the status. The value can be obtained, only if the status is enabled for an entity.
* NULL value for status is allowed and it will reset the trigger value when status is enabled.
*
* @param[in] writer The entity to get the status
* @param[out] status The pointer to \ref DCPS_Status_OfferedDeadlineMissed to get the status
*
* @returns 0 - Success
* @returns <0 - Failure (use dds_err_nr() to get error value).
*
* @retval DDS_RETCODE_ERROR
* An internal error has occurred.
* @retval DDS_RETCODE_BAD_PARAMETER
* One of the given arguments is not valid.
* @retval DDS_RETCODE_ILLEGAL_OPERATION
* The operation is invoked on an inappropriate object.
* @retval DDS_RETCODE_ALREADY_DELETED
* The entity has already been deleted.
*/
_Pre_satisfies_(((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER))
DDS_EXPORT dds_return_t
dds_get_offered_deadline_missed_status(
_In_ dds_entity_t writer,
_Out_opt_ dds_offered_deadline_missed_status_t *status);
/**
* @brief Get OFFERED_INCOMPATIBLE_QOS status
*
* This operation gets the status value corresponding to OFFERED_INCOMPATIBLE_QOS
* and reset the status. The value can be obtained, only if the status is enabled for an entity.
* NULL value for status is allowed and it will reset the trigger value when status is enabled.
*
* @param[in] writer The writer entity to get the status
* @param[out] status The pointer to \ref DCPS_Status_OfferedIncompatibleQoS to get the status
*
* @returns 0 - Success
* @returns <0 - Failure (use dds_err_nr() to get error value).
*
* @retval DDS_RETCODE_ERROR
* An internal error has occurred.
* @retval DDS_RETCODE_BAD_PARAMETER
* One of the given arguments is not valid.
* @retval DDS_RETCODE_ILLEGAL_OPERATION
* The operation is invoked on an inappropriate object.
* @retval DDS_RETCODE_ALREADY_DELETED
* The entity has already been deleted.
*/
_Pre_satisfies_(((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER))
DDS_EXPORT dds_return_t
dds_get_offered_incompatible_qos_status (
_In_ dds_entity_t writer,
_Out_opt_ dds_offered_incompatible_qos_status_t * status);
/**
* @brief Get SUBSCRIPTION_MATCHED status
*
* This operation gets the status value corresponding to SUBSCRIPTION_MATCHED
* and reset the status. The value can be obtained, only if the status is enabled for an entity.
* NULL value for status is allowed and it will reset the trigger value when status is enabled.
*
* @param[in] reader The reader entity to get the status
* @param[out] status The pointer to \ref DCPS_Status_SubscriptionMatched to get the status
*
* @returns 0 - Success
* @returns <0 - Failure (use dds_err_nr() to get error value).
*
* @retval DDS_RETCODE_ERROR
* An internal error has occurred.
* @retval DDS_RETCODE_BAD_PARAMETER
* One of the given arguments is not valid.
* @retval DDS_RETCODE_ILLEGAL_OPERATION
* The operation is invoked on an inappropriate object.
* @retval DDS_RETCODE_ALREADY_DELETED
* The entity has already been deleted.
*/
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER)
DDS_EXPORT dds_return_t
dds_get_subscription_matched_status (
_In_ dds_entity_t reader,
_Out_opt_ dds_subscription_matched_status_t * status);
/**
* @brief Get LIVELINESS_CHANGED status
*
* This operation gets the status value corresponding to LIVELINESS_CHANGED
* and reset the status. The value can be obtained, only if the status is enabled for an entity.
* NULL value for status is allowed and it will reset the trigger value when status is enabled.
*
* @param[in] reader The entity to get the status
* @param[out] status The pointer to \ref DCPS_Status_LivelinessChanged to get the status
*
* @returns 0 - Success
* @returns <0 - Failure (use dds_err_nr() to get error value).
*
* @retval DDS_RETCODE_ERROR
* An internal error has occurred.
* @retval DDS_RETCODE_BAD_PARAMETER
* One of the given arguments is not valid.
* @retval DDS_RETCODE_ILLEGAL_OPERATION
* The operation is invoked on an inappropriate object.
* @retval DDS_RETCODE_ALREADY_DELETED
* The entity has already been deleted.
*/
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER)
DDS_EXPORT dds_return_t
dds_get_liveliness_changed_status (
_In_ dds_entity_t reader,
_Out_opt_ dds_liveliness_changed_status_t * status);
/**
* @brief Get SAMPLE_REJECTED status
*
* This operation gets the status value corresponding to SAMPLE_REJECTED
* and reset the status. The value can be obtained, only if the status is enabled for an entity.
* NULL value for status is allowed and it will reset the trigger value when status is enabled.
*
* @param[in] reader The entity to get the status
* @param[out] status The pointer to \ref DCPS_Status_SampleRejected to get the status
*
* @returns 0 - Success
* @returns <0 - Failure (use dds_err_nr() to get error value).
*
* @retval DDS_RETCODE_ERROR
* An internal error has occurred.
* @retval DDS_RETCODE_BAD_PARAMETER
* One of the given arguments is not valid.
* @retval DDS_RETCODE_ILLEGAL_OPERATION
* The operation is invoked on an inappropriate object.
* @retval DDS_RETCODE_ALREADY_DELETED
* The entity has already been deleted.
*/
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER)
DDS_EXPORT dds_return_t
dds_get_sample_rejected_status (
_In_ dds_entity_t reader,
_Out_opt_ dds_sample_rejected_status_t * status);
/**
* @brief Get SAMPLE_LOST status
*
* This operation gets the status value corresponding to SAMPLE_LOST
* and reset the status. The value can be obtained, only if the status is enabled for an entity.
* NULL value for status is allowed and it will reset the trigger value when status is enabled.
*
* @param[in] reader The entity to get the status
* @param[out] status The pointer to \ref DCPS_Status_SampleLost to get the status
*
* @returns A dds_return_t indicating success or failure
*
* @retval DDS_RETCODE_OK
* Success
* @retval DDS_RETCODE_ERROR
* An internal error has occurred.
* @retval DDS_RETCODE_BAD_PARAMETER
* One of the given arguments is not valid.
* @retval DDS_RETCODE_ILLEGAL_OPERATION
* The operation is invoked on an inappropriate object.
* @retval DDS_RETCODE_ALREADY_DELETED
* The entity has already been deleted.
*/
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER)
DDS_EXPORT dds_return_t
dds_get_sample_lost_status (
_In_ dds_entity_t reader,
_Out_opt_ dds_sample_lost_status_t * status);
/**
* @brief Get REQUESTED_DEADLINE_MISSED status
*
* This operation gets the status value corresponding to REQUESTED_DEADLINE_MISSED
* and reset the status. The value can be obtained, only if the status is enabled for an entity.
* NULL value for status is allowed and it will reset the trigger value when status is enabled.
*
* @param[in] reader The entity to get the status
* @param[out] status The pointer to \ref DCPS_Status_RequestedDeadlineMissed to get the status
*
* @returns A dds_return_t indicating success or failure
*
* @retval DDS_RETCODE_OK
* Success
* @retval DDS_RETCODE_ERROR
* An internal error has occurred.
* @retval DDS_RETCODE_BAD_PARAMETER
* One of the given arguments is not valid.
* @retval DDS_RETCODE_ILLEGAL_OPERATION
* The operation is invoked on an inappropriate object.
* @retval DDS_RETCODE_ALREADY_DELETED
* The entity has already been deleted.
*/
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER)
DDS_EXPORT dds_return_t
dds_get_requested_deadline_missed_status (
_In_ dds_entity_t reader,
_Out_opt_ dds_requested_deadline_missed_status_t * status);
/**
* @brief Get REQUESTED_INCOMPATIBLE_QOS status
*
* This operation gets the status value corresponding to REQUESTED_INCOMPATIBLE_QOS
* and reset the status. The value can be obtained, only if the status is enabled for an entity.
* NULL value for status is allowed and it will reset the trigger value when status is enabled.
*
* @param[in] reader The entity to get the status
* @param[out] status The pointer to \ref DCPS_Status_RequestedIncompatibleQoS to get the status
*
* @returns A dds_return_t indicating success or failure
*
* @retval DDS_RETCODE_OK
* Success
* @retval DDS_RETCODE_ERROR
* An internal error has occurred.
* @retval DDS_RETCODE_BAD_PARAMETER
* One of the given arguments is not valid.
* @retval DDS_RETCODE_ILLEGAL_OPERATION
* The operation is invoked on an inappropriate object.
* @retval DDS_RETCODE_ALREADY_DELETED
* The entity has already been deleted.
*/
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER)
DDS_EXPORT dds_return_t
dds_get_requested_incompatible_qos_status (
_In_ dds_entity_t reader,
_Out_opt_ dds_requested_incompatible_qos_status_t * status);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,101 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
/** @file
*
* @brief DDS C Stream API
*
* This header file defines the public API of the Streams in the
* CycloneDDS C language binding.
*/
#ifndef DDS_STREAM_H
#define DDS_STREAM_H
#include "os/os_public.h"
#include <stdbool.h>
#include "ddsc/dds_export.h"
#if defined (__cplusplus)
extern "C" {
#endif
struct dds_sequence;
typedef union
{
uint8_t * p8;
uint16_t * p16;
uint32_t * p32;
uint64_t * p64;
float * pf;
double * pd;
void * pv;
}
dds_uptr_t;
typedef struct dds_stream
{
dds_uptr_t m_buffer; /* Union of pointers to start of buffer */
size_t m_size; /* Buffer size */
size_t m_index; /* Read/write offset from start of buffer */
bool m_endian; /* Endian: big (false) or little (true) */
bool m_failed; /* Attempt made to read beyond end of buffer */
}
dds_stream_t;
#define DDS_STREAM_BE false
#define DDS_STREAM_LE true
DDS_EXPORT dds_stream_t * dds_stream_create (size_t size);
DDS_EXPORT void dds_stream_delete (dds_stream_t * st);
DDS_EXPORT void dds_stream_fini (dds_stream_t * st);
DDS_EXPORT void dds_stream_reset (dds_stream_t * st);
DDS_EXPORT void dds_stream_init (dds_stream_t * st, size_t size);
DDS_EXPORT void dds_stream_grow (dds_stream_t * st, size_t size);
DDS_EXPORT bool dds_stream_endian (void);
DDS_EXPORT bool dds_stream_read_bool (dds_stream_t * is);
DDS_EXPORT uint8_t dds_stream_read_uint8 (dds_stream_t * is);
DDS_EXPORT uint16_t dds_stream_read_uint16 (dds_stream_t * is);
DDS_EXPORT uint32_t dds_stream_read_uint32 (dds_stream_t * is);
DDS_EXPORT uint64_t dds_stream_read_uint64 (dds_stream_t * is);
DDS_EXPORT float dds_stream_read_float (dds_stream_t * is);
DDS_EXPORT double dds_stream_read_double (dds_stream_t * is);
DDS_EXPORT char * dds_stream_read_string (dds_stream_t * is);
DDS_EXPORT void dds_stream_read_buffer (dds_stream_t * is, uint8_t * buffer, uint32_t len);
#define dds_stream_read_char(s) ((char) dds_stream_read_uint8 (s))
#define dds_stream_read_int8(s) ((int8_t) dds_stream_read_uint8 (s))
#define dds_stream_read_int16(s) ((int16_t) dds_stream_read_uint16 (s))
#define dds_stream_read_int32(s) ((int32_t) dds_stream_read_uint32 (s))
#define dds_stream_read_int64(s) ((int64_t) dds_stream_read_uint64 (s))
DDS_EXPORT void dds_stream_write_bool (dds_stream_t * os, bool val);
DDS_EXPORT void dds_stream_write_uint8 (dds_stream_t * os, uint8_t val);
DDS_EXPORT void dds_stream_write_uint16 (dds_stream_t * os, uint16_t val);
DDS_EXPORT void dds_stream_write_uint32 (dds_stream_t * os, uint32_t val);
DDS_EXPORT void dds_stream_write_uint64 (dds_stream_t * os, uint64_t val);
DDS_EXPORT void dds_stream_write_float (dds_stream_t * os, float val);
DDS_EXPORT void dds_stream_write_double (dds_stream_t * os, double val);
DDS_EXPORT void dds_stream_write_string (dds_stream_t * os, const char * val);
DDS_EXPORT void dds_stream_write_buffer (dds_stream_t * os, uint32_t len, uint8_t * buffer);
#define dds_stream_write_char(s,v) (dds_stream_write_uint8 ((s), (uint8_t)(v)))
#define dds_stream_write_int8(s,v) (dds_stream_write_uint8 ((s), (uint8_t)(v)))
#define dds_stream_write_int16(s,v) (dds_stream_write_uint16 ((s), (uint16_t)(v)))
#define dds_stream_write_int32(s,v) (dds_stream_write_uint32 ((s), (uint32_t)(v)))
#define dds_stream_write_int64(s,v) (dds_stream_write_uint64 ((s), (uint64_t)(v)))
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,96 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
/** @file
*
* @brief DDS C Time support API
*
* This header file defines the public API of the in the
* CycloneDDS C language binding.
*/
#ifndef DDS_TIME_H
#define DDS_TIME_H
#include "os/os_public.h"
#include "ddsc/dds_export.h"
#if defined (__cplusplus)
extern "C" {
#endif
/*
Times are represented using a 64-bit signed integer, encoding
nanoseconds since the epoch. Considering the nature of these
systems, one would best use TAI, International Atomic Time, rather
than something UTC, but availability may be limited.
Valid times are non-negative and times up to 2**63-2 can be
represented. 2**63-1 is defined to represent, essentially, "never".
This is good enough for a couple of centuries.
*/
/** Absolute Time definition */
typedef int64_t dds_time_t;
/** Relative Time definition */
typedef int64_t dds_duration_t;
/** @name Macro definition for time units in nanoseconds.
@{**/
#define DDS_NSECS_IN_SEC 1000000000LL
#define DDS_NSECS_IN_MSEC 1000000LL
#define DDS_NSECS_IN_USEC 1000LL
/** @}*/
/** @name Infinite timeout for indicate absolute time */
#define DDS_NEVER ((dds_time_t) INT64_MAX)
/** @name Infinite timeout for relative time */
#define DDS_INFINITY ((dds_duration_t) INT64_MAX)
/** @name Macro definition for time conversion from nanoseconds
@{**/
#define DDS_SECS(n) ((n) * DDS_NSECS_IN_SEC)
#define DDS_MSECS(n) ((n) * DDS_NSECS_IN_MSEC)
#define DDS_USECS(n) ((n) * DDS_NSECS_IN_USEC)
/** @}*/
/**
* Description : This operation returns the current time (in nanoseconds)
*
* Arguments :
* -# Returns current time
*/
DDS_EXPORT dds_time_t dds_time (void);
/**
* Description : This operation blocks the calling thread until the relative time
* n has elapsed
*
* Arguments :
* -# n Relative Time to block a thread
*/
DDS_EXPORT void dds_sleepfor (dds_duration_t n);
/**
* Description : This operation blocks the calling thread until the absolute time
* n has elapsed
*
* Arguments :
* -# n absolute Time to block a thread
*/
DDS_EXPORT void dds_sleepuntil (dds_time_t n);
#if defined (__cplusplus)
}
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,26 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_ALLOC_H_
#define _DDS_ALLOC_H_
#include "dds__types.h"
#if defined (__cplusplus)
extern "C" {
#endif
void dds_sample_free_contents (char * data, const uint32_t * ops);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,72 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_BUILTIN_H_
#define _DDS_BUILTIN_H_
#include "ddsi/q_time.h"
#include "dds_builtinTopics.h"
#if defined (__cplusplus)
extern "C"
{
#endif
/* Get actual topic in related participant related to topic 'id'. */
_Must_inspect_result_ dds_entity_t
dds__get_builtin_topic(
_In_ dds_entity_t e,
_In_ dds_entity_t topic);
/* Global publisher singleton (publishes only locally). */
_Must_inspect_result_ dds_entity_t
dds__get_builtin_publisher(
void);
/* Subscriber singleton within related participant. */
_Must_inspect_result_ dds_entity_t
dds__get_builtin_subscriber(
_In_ dds_entity_t e);
/* Initialization and finalize functions. */
void
dds__builtin_init(
void);
void
dds__builtin_fini(
void);
/* Callback functions that contain received builtin data. */
void
dds__builtin_participant_cb(
DDS_ParticipantBuiltinTopicData *data,
nn_wctime_t timestamp);
void
dds__builtin_cmparticipant_cb(
DDS_CMParticipantBuiltinTopicData *data,
nn_wctime_t timestamp);
#if defined (__cplusplus)
}
#endif
#endif /* _DDS_BUILTIN_H_ */

View file

@ -0,0 +1,30 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_DOMAIN_H_
#define _DDS_DOMAIN_H_
#include "dds__types.h"
#if defined (__cplusplus)
extern "C" {
#endif
extern const ut_avlTreedef_t dds_domaintree_def;
extern dds_domain * dds_domain_create (dds_domainid_t id);
extern void dds_domain_free (dds_domain * domain);
extern dds_domain * dds_domain_find_locked (dds_domainid_t id);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,114 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_ENTITY_H_
#define _DDS_ENTITY_H_
#include "dds__types.h"
#include "ddsi/q_thread.h"
#if defined (__cplusplus)
extern "C" {
#endif
_Check_return_ dds_entity_t
dds_entity_init(
_In_ dds_entity * e,
_When_(kind != DDS_KIND_PARTICIPANT, _Notnull_)
_When_(kind == DDS_KIND_PARTICIPANT, _Null_)
_In_opt_ dds_entity * parent,
_In_ dds_entity_kind_t kind,
_In_opt_ dds_qos_t * qos,
_In_opt_ const dds_listener_t *listener,
_In_ uint32_t mask);
void
dds_entity_add_ref(
_In_ dds_entity *e);
void
dds_entity_add_ref_nolock(
_In_ dds_entity *e);
_Check_return_ dds__retcode_t
dds_entity_listener_propagation(
_Inout_opt_ dds_entity *e,
_In_ dds_entity *src,
_In_ uint32_t status,
_In_opt_ void *metrics,
_In_ bool propagate);
#define dds_entity_is_enabled(e, k) (((dds_entity*)e)->m_flags & DDS_ENTITY_ENABLED)
#define dds_entity_status_set(e, t) (((dds_entity*)e)->m_trigger |= (((dds_entity*)e)->m_status_enable & t))
#define dds_entity_status_reset(e,t) (((dds_entity*)e)->m_trigger &= ~t)
#define dds_entity_status_match(e,t) (((dds_entity*)e)->m_trigger & t)
/* The mutex needs to be unlocked when calling this because the entity can be called
* within the signal callback from other contexts. That shouldn't deadlock. */
void
dds_entity_status_signal(
_In_ dds_entity *e);
_Check_return_ dds__retcode_t
dds_valid_hdl(
_In_ dds_entity_t hdl,
_In_ dds_entity_kind_t kind);
_Acquires_exclusive_lock_(*e)
_Check_return_ dds__retcode_t
dds_entity_lock(
_In_ dds_entity_t hdl,
_In_ dds_entity_kind_t kind,
_Out_ dds_entity **e);
_Releases_exclusive_lock_(e)
void
dds_entity_unlock(
_Inout_ dds_entity *e);
#define dds_entity_kind(hdl) ((hdl > 0) ? (hdl & DDS_ENTITY_KIND_MASK) : 0)
_Check_return_ dds__retcode_t
dds_entity_observer_register_nl(
_In_ dds_entity* observed,
_In_ dds_entity_t observer,
_In_ dds_entity_callback cb);
_Check_return_ dds__retcode_t
dds_entity_observer_register(
_In_ dds_entity_t observed,
_In_ dds_entity_t observer,
_In_ dds_entity_callback cb);
dds__retcode_t
dds_entity_observer_unregister_nl(
_In_ dds_entity* observed,
_In_ dds_entity_t observer);
dds__retcode_t
dds_entity_observer_unregister(
_In_ dds_entity_t observed,
_In_ dds_entity_t observer);
_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK)
dds_return_t
dds_delete_impl(
_In_ dds_entity_t entity,
_In_ bool keep_if_explicit);
const char *
dds__entity_kind_str(
_In_ dds_entity_t e);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,41 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_ERR_H_
#define _DDS_ERR_H_
#include <assert.h>
#include "os/os.h"
#if defined (__cplusplus)
extern "C" {
#endif
/* To construct return status
* Use '+' instead of '|'. Otherwise, the SAL checking doesn't
* understand when a return value is negative or positive and
* complains a lot about "A successful path through the function
* does not set the named _Out_ parameter." */
#if !defined(__FILE_ID__)
#error "__FILE_ID__ not defined"
#endif
#define DDS__FILE_ID__ (((__FILE_ID__ & 0x1ff)) << 22)
#define DDS__LINE__ ((__LINE__ & 0x3fff) << 8)
#define DDS_ERR_NO(err) -(DDS__FILE_ID__ + DDS__LINE__ + (err))
#define DDS_ERRNO(e,msg,...) (assert(e > DDS_RETCODE_OK), os_report(OS_REPORT_ERROR, OS_FUNCTION, __FILE__, __LINE__, DDS_ERR_NO(e), (msg), ##__VA_ARGS__), DDS_ERR_NO(e))
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,28 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_IID_H_
#define _DDS_IID_H_
#include "dds__types.h"
#if defined (__cplusplus)
extern "C" {
#endif
void dds_iid_init (void);
void dds_iid_fini (void);
uint64_t dds_iid_gen (void);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,78 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_INIT_H_
#define _DDS_INIT_H_
#include "dds__types.h"
#if defined (__cplusplus)
extern "C" {
#endif
dds_return_t
dds__check_domain(
_In_ dds_domainid_t domain);
/**
*Description : Initialization function. This operation initializes all the
*required resources that are needed for the DDSC API process lifecycle
*(like the init mutex and os layer).
*A function will be registered that is called at the end of the process
*lifecycle and will destroy the resources initialized in this function.
**/
void
dds__startup(void);
/**
*Description : Initialization function, called from main. This operation
*initializes all the required DDS resources,
*handles configuration of domainid based on the input passed, parses and
*configures middleware from a xml file and initializes required resources.
*
*Arguments :
*-# Returns 0 on success or a non-zero error status
**/
dds_return_t
dds_init(void);
/* Finalization function, called from main */
/**
*Description : Finalization function, called from main. This operation
*releases all the resources used by DDS.
*
*Arguments :
*-# None
**/
void
dds_fini(void);
/**
* Description : Function that provides the explicit ID of default domain
* It should be called after DDS initialization.
* @return Valid domain id. Undetermined behaviour if DDS is not initialized.
*/
dds_domainid_t dds_domain_default (void);
/**
* Description : Mutex used for initialization synchronization.
*/
extern os_mutex dds__init_mutex;
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,35 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_KEY_H_
#define _DDS_KEY_H_
#include "dds__types.h"
struct dds_key_hash;
#if defined (__cplusplus)
extern "C" {
#endif
void dds_key_md5 (struct dds_key_hash * kh);
void dds_key_gen
(
const dds_topic_descriptor_t * const desc,
struct dds_key_hash * kh,
const char * sample
);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,31 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_LISTENER_H_
#define _DDS_LISTENER_H_
#include "dds__types.h"
#include "ddsc/dds_public_listener.h"
#if defined (__cplusplus)
extern "C" {
#endif
/*
* Listener API (internal & external) are present in
* dds__types.h
* ddsc/dds_public_listener.h
*/
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,23 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_PPANT_H_
#define _DDS_PPANT_H_
#if defined (__cplusplus)
extern "C" {
#endif
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,27 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_PUBLISHER_H_
#define _DDS_PUBLISHER_H_
#include "ddsc/dds.h"
#if defined (__cplusplus)
extern "C" {
#endif
dds_return_t dds_publisher_begin_coherent (dds_entity_t e);
dds_return_t dds_publisher_end_coherent (dds_entity_t e);
#if defined (__cplusplus)
}
#endif
#endif /* _DDS_PUBLISHER_H_ */

View file

@ -0,0 +1,37 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_QOS_H_
#define _DDS_QOS_H_
#include "dds__entity.h"
#include "ddsi/q_xqos.h"
#include "ddsi/q_time.h"
#include "ddsi/q_plist.h"
#if defined (__cplusplus)
extern "C" {
#endif
bool validate_deadline_and_timebased_filter (const nn_duration_t deadline, const nn_duration_t minimum_separation);
bool validate_entityfactory_qospolicy (const nn_entity_factory_qospolicy_t * entityfactory);
bool validate_octetseq (const nn_octetseq_t* seq);
bool validate_partition_qospolicy (_In_ const nn_partition_qospolicy_t * partition);
bool validate_reliability_qospolicy (const nn_reliability_qospolicy_t * reliability);
bool validate_stringseq (const nn_stringseq_t* seq);
bool dds_qos_validate_common (const dds_qos_t *qos);
dds_return_t dds_qos_validate_mutable_common (_In_ const dds_qos_t *qos);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,23 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_QUERYCOND_H_
#define _DDS_QUERYCOND_H_
#if defined (__cplusplus)
extern "C"
{
#endif
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,23 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_READCOND_H_
#define _DDS_READCOND_H_
#include "dds__entity.h"
_Must_inspect_result_ dds_readcond*
dds_create_readcond(
_In_ dds_reader *rd,
_In_ dds_entity_kind_t kind,
_In_ uint32_t mask);
#endif

View file

@ -0,0 +1,49 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_READER_H_
#define _DDS_READER_H_
#include "dds__types.h"
#if defined (__cplusplus)
extern "C" {
#endif
struct status_cb_data;
void dds_reader_status_cb (void * entity, const struct status_cb_data * data);
/*
dds_reader_lock_samples: Returns number of samples in read cache and locks the
reader cache to make sure that the samples content doesn't change.
Because the cache is locked, you should be able to read/take without having to
lock first. This is done by passing the DDS_READ_WITHOUT_LOCK value to the
read/take call as maxs. Then the read/take will not lock but still unlock.
See also CHAM-287, CHAM-306 and LITE-1183.
Used to support LENGTH_UNLIMITED in C++.
*/
#define DDS_READ_WITHOUT_LOCK (0xFFFFFFED)
DDS_EXPORT uint32_t dds_reader_lock_samples (dds_entity_t entity);
struct nn_rsample_info;
struct nn_rdata;
DDS_EXPORT void dds_reader_ddsi2direct (dds_entity_t entity, void (*cb) (const struct nn_rsample_info *sampleinfo, const struct nn_rdata *fragchain, void *arg), void *cbarg);
#define dds_reader_lock(hdl, obj) dds_entity_lock(hdl, DDS_KIND_READER, (dds_entity**)obj)
#define dds_reader_unlock(obj) dds_entity_unlock((dds_entity*)obj);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,78 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef DDS_REPORT_H
#define DDS_REPORT_H
#include <stdarg.h>
#include "os/os_report.h"
#define DDS_REPORT_STACK() \
os_report_stack ()
#define DDS_CRITICAL(...) \
dds_report ( \
OS_REPORT_CRITICAL, \
__FILE__, \
__LINE__, \
OS_FUNCTION, \
DDS_RETCODE_ERROR, \
__VA_ARGS__)
#define DDS_ERROR(code,...) \
dds_report ( \
OS_REPORT_ERROR, \
__FILE__, \
__LINE__, \
OS_FUNCTION, \
(code), \
__VA_ARGS__)
#define DDS_INFO(...) \
dds_report ( \
OS_REPORT_INFO, \
__FILE__, \
__LINE__, \
OS_FUNCTION, \
DDS_RETCODE_OK, \
__VA_ARGS__)
#define DDS_WARNING(code,...) \
dds_report ( \
OS_REPORT_WARNING, \
__FILE__, \
__LINE__, \
OS_FUNCTION, \
(code), \
__VA_ARGS__)
#define DDS_REPORT(type, code,...) \
dds_report ( \
type, \
__FILE__, \
__LINE__, \
OS_FUNCTION, \
(code), \
__VA_ARGS__)
#define DDS_REPORT_FLUSH OS_REPORT_FLUSH
void
dds_report(
os_reportType reportType,
const char *file,
int32_t line,
const char *function,
dds_return_t code,
const char *format,
...);
#endif

View file

@ -0,0 +1,86 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_RHC_H_
#define _DDS_RHC_H_
#include "os/os_defs.h"
#define NO_STATE_MASK_SET (DDS_ANY_STATE + 1)
#if defined (__cplusplus)
extern "C" {
#endif
struct rhc;
struct nn_xqos;
struct serdata;
struct tkmap_instance;
struct tkmap;
struct nn_rsample_info;
struct proxy_writer_info;
struct rhc * dds_rhc_new (dds_reader * reader, const struct sertopic * topic);
void dds_rhc_free (struct rhc * rhc);
void dds_rhc_fini (struct rhc * rhc);
uint32_t dds_rhc_lock_samples (struct rhc * rhc);
DDS_EXPORT bool dds_rhc_store
(
struct rhc * __restrict rhc, const struct nn_rsample_info * __restrict sampleinfo,
struct serdata * __restrict sample, struct tkmap_instance * __restrict tk
);
void dds_rhc_unregister_wr (struct rhc * __restrict rhc, const struct proxy_writer_info * __restrict pwr_info);
void dds_rhc_relinquish_ownership (struct rhc * __restrict rhc, const uint64_t wr_iid);
int
dds_rhc_read(
struct rhc *rhc,
bool lock,
void ** values,
dds_sample_info_t *info_seq,
uint32_t max_samples,
uint32_t mask,
dds_instance_handle_t handle,
dds_readcond *cond);
int
dds_rhc_take(
struct rhc *rhc,
bool lock,
void ** values,
dds_sample_info_t *info_seq,
uint32_t max_samples,
uint32_t mask,
dds_instance_handle_t handle,
dds_readcond *cond);
void dds_rhc_set_qos (struct rhc * rhc, const struct nn_xqos * qos);
void dds_rhc_add_readcondition (dds_readcond * cond);
void dds_rhc_remove_readcondition (dds_readcond * cond);
bool dds_rhc_add_waitset (dds_readcond * cond, dds_waitset * waitset, dds_attach_t x);
int dds_rhc_remove_waitset (dds_readcond * cond, dds_waitset * waitset);
int dds_rhc_takecdr
(
struct rhc *rhc, bool lock, struct serdata **values, dds_sample_info_t *info_seq,
uint32_t max_samples, unsigned sample_states,
unsigned view_states, unsigned instance_states,
dds_instance_handle_t handle
);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,88 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_STREAM_H_
#define _DDS_STREAM_H_
#include "ddsi/ddsi_ser.h"
#if defined (__cplusplus)
extern "C" {
#endif
void dds_stream_write_sample
(
dds_stream_t * os,
const void * data,
const struct sertopic * topic
);
void dds_stream_read_sample
(
dds_stream_t * is,
void * data,
const struct sertopic * topic
);
size_t dds_stream_check_optimize (_In_ const dds_topic_descriptor_t * desc);
void dds_stream_from_serstate (_Out_ dds_stream_t * s, _In_ const serstate_t st);
void dds_stream_add_to_serstate (_Inout_ dds_stream_t * s, _Inout_ serstate_t st);
void dds_stream_write_key
(
dds_stream_t * os,
const char * sample,
const dds_topic_descriptor_t * desc
);
void dds_stream_read_key
(
dds_stream_t * is,
char * sample,
const dds_topic_descriptor_t * desc
);
void dds_stream_read_keyhash
(
dds_stream_t * is,
dds_key_hash_t * kh,
const dds_topic_descriptor_t * desc,
const bool just_key
);
char * dds_stream_reuse_string
(
dds_stream_t * is,
char * str,
const uint32_t bound
);
DDS_EXPORT void dds_stream_swap (void * buff, uint32_t size, uint32_t num);
extern const uint32_t dds_op_size[5];
/* For marshalling op code handling */
#define DDS_OP_MASK 0xff000000
#define DDS_OP_TYPE_MASK 0x00ff0000
#define DDS_OP_SUBTYPE_MASK 0x0000ff00
#define DDS_OP_JMP_MASK 0x0000ffff
#define DDS_OP_FLAGS_MASK 0x000000ff
#define DDS_JEQ_TYPE_MASK 0x00ff0000
#define DDS_OP(o) ((o) & DDS_OP_MASK)
#define DDS_OP_TYPE(o) (((o) & DDS_OP_TYPE_MASK) >> 16)
#define DDS_OP_SUBTYPE(o) (((o) & DDS_OP_SUBTYPE_MASK) >> 8)
#define DDS_OP_FLAGS(o) ((o) & DDS_OP_FLAGS_MASK)
#define DDS_OP_ADR_JSR(o) ((o) & DDS_OP_JMP_MASK)
#define DDS_OP_JUMP(o) ((int16_t) ((o) & DDS_OP_JMP_MASK))
#define DDS_OP_ADR_JMP(o) ((o) >> 16)
#define DDS_JEQ_TYPE(o) (((o) & DDS_JEQ_TYPE_MASK) >> 16)
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,41 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_SUBSCRIBER_H_
#define _DDS_SUBSCRIBER_H_
#include "ddsc/dds.h"
#if defined (__cplusplus)
extern "C" {
#endif
struct dds_entity;
_Requires_exclusive_lock_held_(participant)
_Check_return_ dds_entity_t
dds__create_subscriber_l(
_Inout_ struct dds_entity *participant, /* entity-lock must be held */
_In_opt_ const dds_qos_t *qos,
_In_opt_ const dds_listener_t *listener);
dds_return_t
dds_subscriber_begin_coherent(
_In_ dds_entity_t e);
dds_return_t
dds_subscriber_end_coherent (
_In_ dds_entity_t e);
#if defined (__cplusplus)
}
#endif
#endif /* _DDS_SUBSCRIBER_H_ */

View file

@ -0,0 +1,53 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_TKMAP_H_
#define _DDS_TKMAP_H_
#include "dds__types.h"
#include "os/os_atomics.h"
#if defined (__cplusplus)
extern "C" {
#endif
struct tkmap;
struct serdata;
struct dds_topic;
struct tkmap_instance
{
struct serdata * m_sample;
struct tkmap * m_map;
uint64_t m_iid;
os_atomic_uint32_t m_refc;
};
struct tkmap * dds_tkmap_new (void);
void dds_tkmap_free (_Inout_ _Post_invalid_ struct tkmap *tkmap);
void dds_tkmap_instance_ref (_In_ struct tkmap_instance *tk);
uint64_t dds_tkmap_lookup (_In_ struct tkmap *tkmap, _In_ const struct serdata *serdata);
_Check_return_ bool dds_tkmap_get_key (_In_ struct tkmap * map, _In_ uint64_t iid, _Out_ void * sample);
_Check_return_ struct tkmap_instance * dds_tkmap_find(
_In_opt_ const struct dds_topic * topic,
_In_ struct serdata * sd,
_In_ const bool rd,
_In_ const bool create);
_Check_return_ struct tkmap_instance * dds_tkmap_find_by_id (_In_ struct tkmap * map, _In_ uint64_t iid);
DDS_EXPORT _Check_return_ struct tkmap_instance * dds_tkmap_lookup_instance_ref (_In_ struct serdata * sd);
DDS_EXPORT void dds_tkmap_instance_unref (_In_ struct tkmap_instance * tk);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,41 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_TOPIC_H_
#define _DDS_TOPIC_H_
#include "dds__types.h"
#if defined (__cplusplus)
extern "C" {
#endif
#define dds_topic_lock(hdl, obj) dds_entity_lock(hdl, DDS_KIND_TOPIC, (dds_entity**)obj)
#define dds_topic_unlock(obj) dds_entity_unlock((dds_entity*)obj);
extern struct sertopic * dds_topic_lookup (dds_domain * domain, const char * name);
extern void dds_topic_free (dds_domainid_t domainid, struct sertopic * st);
#ifndef DDS_TOPIC_INTERN_FILTER_FN_DEFINED
#define DDS_TOPIC_INTERN_FILTER_FN_DEFINED
typedef bool (*dds_topic_intern_filter_fn) (const void * sample, void *ctx);
#endif
DDS_EXPORT void dds_topic_set_filter_with_ctx
(dds_entity_t topic, dds_topic_intern_filter_fn filter, void *ctx);
DDS_EXPORT dds_topic_intern_filter_fn dds_topic_get_filter_with_ctx
(dds_entity_t topic);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,273 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_TYPES_H_
#define _DDS_TYPES_H_
/* DDS internal type definitions */
#include "os/os.h"
#include "ddsc/dds.h"
#include "ddsi/q_rtps.h"
#include "util/ut_avl.h"
#include "util/ut_handleserver.h"
#if defined (__cplusplus)
extern "C" {
#endif
typedef _Return_type_success_(return == DDS_RETCODE_OK) int32_t dds__retcode_t;
struct dds_domain;
struct dds_entity;
struct dds_participant;
struct dds_reader;
struct dds_writer;
struct dds_publisher;
struct dds_subscriber;
struct dds_topic;
struct dds_readcond;
struct dds_guardcond;
struct sertopic;
struct rhc;
/* Internal entity status flags */
#define DDS_INTERNAL_STATUS_MASK (0xFF000000)
#define DDS_WAITSET_TRIGGER_STATUS (0x01000000)
#define DDS_DELETING_STATUS (0x02000000)
/* This can be used when polling for various states.
* Obviously, it is encouraged to use condition variables and such. But
* sometimes it wouldn't make that much of a difference and taking the
* easy route is somewhat pragmatic. */
#define DDS_HEADBANG_TIMEOUT_MS (10)
typedef bool (*dds_querycondition_filter_with_ctx_fn) (const void * sample, const void *ctx);
/* The listener struct. */
typedef struct c_listener {
dds_on_inconsistent_topic_fn on_inconsistent_topic;
dds_on_liveliness_lost_fn on_liveliness_lost;
dds_on_offered_deadline_missed_fn on_offered_deadline_missed;
dds_on_offered_incompatible_qos_fn on_offered_incompatible_qos;
dds_on_data_on_readers_fn on_data_on_readers;
dds_on_sample_lost_fn on_sample_lost;
dds_on_data_available_fn on_data_available;
dds_on_sample_rejected_fn on_sample_rejected;
dds_on_liveliness_changed_fn on_liveliness_changed;
dds_on_requested_deadline_missed_fn on_requested_deadline_missed;
dds_on_requested_incompatible_qos_fn on_requested_incompatible_qos;
dds_on_publication_matched_fn on_publication_matched;
dds_on_subscription_matched_fn on_subscription_matched;
void *arg;
} c_listener_t;
/* Entity flag values */
#define DDS_ENTITY_ENABLED 0x0001
#define DDS_ENTITY_IMPLICIT 0x0002
typedef struct dds_domain
{
ut_avlNode_t m_node;
dds_domainid_t m_id;
ut_avlTree_t m_topics;
uint32_t m_refc;
}
dds_domain;
struct dds_entity;
typedef struct dds_entity_deriver {
/* Close can be used to terminate (blocking) actions on a entity before actually deleting it. */
dds_return_t (*close)(struct dds_entity *e);
/* Delete is used to actually free the entity. */
dds_return_t (*delete)(struct dds_entity *e);
dds_return_t (*set_qos)(struct dds_entity *e, const dds_qos_t *qos, bool enabled);
dds_return_t (*validate_status)(uint32_t mask);
dds_return_t (*propagate_status)(struct dds_entity *e, uint32_t mask, bool set);
dds_return_t (*get_instance_hdl)(struct dds_entity *e, dds_instance_handle_t *i);
}
dds_entity_deriver;
typedef void (*dds_entity_callback)(dds_entity_t observer, dds_entity_t observed, uint32_t status);
typedef struct dds_entity_observer
{
dds_entity_callback m_cb;
dds_entity_t m_observer;
struct dds_entity_observer *m_next;
}
dds_entity_observer;
typedef struct dds_entity
{
ut_handle_t m_hdl;
dds_entity_deriver m_deriver;
uint32_t m_refc;
struct dds_entity * m_next;
struct dds_entity * m_parent;
struct dds_entity * m_children;
struct dds_entity * m_participant;
struct dds_domain * m_domain;
dds_qos_t * m_qos;
dds_domainid_t m_domainid;
nn_guid_t m_guid;
uint32_t m_status_enable;
uint32_t m_flags;
uint32_t m_cb_count;
os_mutex m_mutex;
os_cond m_cond;
c_listener_t m_listener;
uint32_t m_trigger;
dds_entity_observer *m_observers;
struct ut_handlelink *m_hdllink;
}
dds_entity;
extern const ut_avlTreedef_t dds_topictree_def;
typedef struct dds_subscriber
{
struct dds_entity m_entity;
}
dds_subscriber;
typedef struct dds_publisher
{
struct dds_entity m_entity;
}
dds_publisher;
typedef struct dds_participant
{
struct dds_entity m_entity;
struct dds_entity * m_dur_reader;
struct dds_entity * m_dur_writer;
dds_entity_t m_builtin_subscriber;
}
dds_participant;
typedef struct dds_reader
{
struct dds_entity m_entity;
const struct dds_topic * m_topic;
struct reader * m_rd;
bool m_data_on_readers;
bool m_loan_out;
char * m_loan;
uint32_t m_loan_size;
/* Status metrics */
dds_sample_rejected_status_t m_sample_rejected_status;
dds_liveliness_changed_status_t m_liveliness_changed_status;
dds_requested_deadline_missed_status_t m_requested_deadline_missed_status;
dds_requested_incompatible_qos_status_t m_requested_incompatible_qos_status;
dds_sample_lost_status_t m_sample_lost_status;
dds_subscription_matched_status_t m_subscription_matched_status;
}
dds_reader;
typedef struct dds_writer
{
struct dds_entity m_entity;
const struct dds_topic * m_topic;
struct nn_xpack * m_xp;
struct writer * m_wr;
os_mutex m_call_lock;
/* Status metrics */
dds_liveliness_lost_status_t m_liveliness_lost_status;
dds_offered_deadline_missed_status_t m_offered_deadline_missed_status;
dds_offered_incompatible_qos_status_t m_offered_incompatible_qos_status;
dds_publication_matched_status_t m_publication_matched_status;
}
dds_writer;
typedef struct dds_topic
{
struct dds_entity m_entity;
struct sertopic * m_stopic;
const dds_topic_descriptor_t * m_descriptor;
/* Status metrics */
dds_inconsistent_topic_status_t m_inconsistent_topic_status;
}
dds_topic;
typedef struct dds_readcond
{
dds_entity m_entity;
struct rhc * m_rhc;
uint32_t m_qminv;
uint32_t m_sample_states;
uint32_t m_view_states;
uint32_t m_instance_states;
nn_guid_t m_rd_guid;
struct dds_readcond * m_rhc_next;
struct
{
dds_querycondition_filter_fn m_filter;
} m_query;
}
dds_readcond;
typedef struct dds_attachment
{
dds_entity *entity;
dds_attach_t arg;
struct dds_attachment* next;
}
dds_attachment;
typedef struct dds_waitset
{
dds_entity m_entity;
dds_attachment *observed;
dds_attachment *triggered;
}
dds_waitset;
typedef struct dds_iid
{
uint64_t counter;
uint32_t key[4];
}
dds_iid;
/* Globals */
typedef struct dds_globals
{
dds_domainid_t m_default_domain;
int32_t m_init_count;
void (*m_dur_reader) (struct dds_reader * reader, struct rhc * rhc);
int (*m_dur_wait) (struct dds_reader * reader, dds_duration_t timeout);
void (*m_dur_init) (void);
void (*m_dur_fini) (void);
ut_avlTree_t m_domains;
os_mutex m_mutex;
}
dds_globals;
DDS_EXPORT extern dds_globals dds_global;
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,51 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_WRITE_H_
#define _DDS_WRITE_H_
#if defined (__cplusplus)
extern "C" {
#endif
#define DDS_WR_KEY_BIT 0x01
#define DDS_WR_DISPOSE_BIT 0x02
#define DDS_WR_UNREGISTER_BIT 0x04
typedef enum
{
DDS_WR_ACTION_WRITE = 0,
DDS_WR_ACTION_WRITE_DISPOSE = DDS_WR_DISPOSE_BIT,
DDS_WR_ACTION_DISPOSE = DDS_WR_KEY_BIT | DDS_WR_DISPOSE_BIT,
DDS_WR_ACTION_UNREGISTER = DDS_WR_KEY_BIT | DDS_WR_UNREGISTER_BIT
}
dds_write_action;
int
dds_write_impl(
_In_ dds_writer *wr,
_In_ const void *data,
_In_ dds_time_t tstamp,
_In_ dds_write_action action);
int
dds_writecdr_impl(
_In_ dds_writer *wr,
_In_ const void *cdr,
_In_ size_t sz,
_In_ dds_time_t tstamp,
_In_ dds_write_action action);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,27 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef _DDS_WRITER_H_
#define _DDS_WRITER_H_
#include "dds__entity.h"
#if defined (__cplusplus)
extern "C" {
#endif
#define dds_writer_lock(hdl, obj) dds_entity_lock(hdl, DDS_KIND_WRITER, (dds_entity**)obj)
#define dds_writer_unlock(obj) dds_entity_unlock((dds_entity*)obj);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,371 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include "dds__alloc.h"
#include "dds__stream.h"
#include "os/os_heap.h"
#include "ddsi/q_config.h"
/*
#define OP_DEBUG_FREE 1
*/
#if defined OP_DEBUG_FREE
static const char * stream_op_type[11] =
{
NULL, "1Byte", "2Byte", "4Byte", "8Byte", "String",
"BString", "Sequence", "Array", "Union", "Struct"
};
#endif
static dds_allocator_t dds_allocator_fns = { os_malloc, os_realloc, os_free };
void * dds_alloc (size_t size)
{
void * ret = (dds_allocator_fns.malloc) (size);
if (ret)
{
memset (ret, 0, size);
}
else
{
DDS_FAIL ("dds_alloc");
}
return ret;
}
void * dds_realloc (void * ptr, size_t size)
{
void * ret = (dds_allocator_fns.realloc) (ptr, size);
if (ret == NULL) DDS_FAIL ("dds_realloc");
return ret;
}
void * dds_realloc_zero (void * ptr, size_t size)
{
void * ret = dds_realloc (ptr, size);
if (ret)
{
memset (ret, 0, size);
}
return ret;
}
void dds_free (void * ptr)
{
if (ptr) (dds_allocator_fns.free) (ptr);
}
char * dds_string_alloc (size_t size)
{
return (char*) dds_alloc (size + 1);
}
char * dds_string_dup (const char * str)
{
char * ret = NULL;
if (str)
{
ret = dds_alloc (strlen (str) + 1);
strcpy (ret, str);
}
return ret;
}
void dds_string_free (char * str)
{
dds_free (str);
}
void dds_sample_free_contents (char * data, const uint32_t * ops)
{
uint32_t op;
uint32_t type;
uint32_t num;
uint32_t subtype;
char * addr;
while ((op = *ops) != DDS_OP_RTS)
{
switch (DDS_OP_MASK & op)
{
case DDS_OP_ADR:
{
type = DDS_OP_TYPE (op);
#ifdef OP_DEBUG_FREE
TRACE (("F-ADR: %s offset %d\n", stream_op_type[type], ops[1]));
#endif
addr = data + ops[1];
ops += 2;
switch (type)
{
case DDS_OP_VAL_1BY:
case DDS_OP_VAL_2BY:
case DDS_OP_VAL_4BY:
case DDS_OP_VAL_8BY:
{
break;
}
case DDS_OP_VAL_STR:
{
#ifdef OP_DEBUG_FREE
TRACE (("F-STR: @ %p %s\n", addr, *((char**) addr)));
#endif
dds_free (*((char**) addr));
*((char**) addr) = NULL;
break;
}
case DDS_OP_VAL_SEQ:
{
dds_sequence_t * seq = (dds_sequence_t*) addr;
subtype = DDS_OP_SUBTYPE (op);
num = (seq->_maximum > seq->_length) ? seq->_maximum : seq->_length;
#ifdef OP_DEBUG_FREE
TRACE (("F-SEQ: of %s\n", stream_op_type[subtype]));
#endif
if ((seq->_release && num) || (subtype > DDS_OP_VAL_STR))
{
switch (subtype)
{
case DDS_OP_VAL_1BY:
case DDS_OP_VAL_2BY:
case DDS_OP_VAL_4BY:
case DDS_OP_VAL_8BY:
{
break;
}
case DDS_OP_VAL_BST:
{
ops++;
break;
}
case DDS_OP_VAL_STR:
{
char ** ptr = (char**) seq->_buffer;
while (num--)
{
dds_free (*ptr++);
}
break;
}
default:
{
const uint32_t elem_size = *ops++;
const uint32_t * jsr_ops = ops + DDS_OP_ADR_JSR (*ops) - 3;
const uint32_t jmp = DDS_OP_ADR_JMP (*ops);
char * ptr = (char*) seq->_buffer;
while (num--)
{
dds_sample_free_contents (ptr, jsr_ops);
ptr += elem_size;
}
ops += jmp ? (jmp - 3) : 1;
break;
}
}
}
if (seq->_release)
{
dds_free (seq->_buffer);
seq->_buffer = NULL;
}
break;
}
case DDS_OP_VAL_ARR:
{
subtype = DDS_OP_SUBTYPE (op);
num = *ops++;
#ifdef OP_DEBUG_FREE
TRACE (("F-ARR: of %s size %d\n", stream_op_type[subtype], num));
#endif
switch (subtype)
{
case DDS_OP_VAL_1BY:
case DDS_OP_VAL_2BY:
case DDS_OP_VAL_4BY:
case DDS_OP_VAL_8BY:
{
break;
}
case DDS_OP_VAL_STR:
{
char ** ptr = (char**) addr;
while (num--)
{
dds_free (*ptr++);
}
break;
}
case DDS_OP_VAL_BST:
{
ops += 2;
break;
}
default:
{
const uint32_t * jsr_ops = ops + DDS_OP_ADR_JSR (*ops) - 3;
const uint32_t jmp = DDS_OP_ADR_JMP (*ops);
const uint32_t elem_size = ops[1];
while (num--)
{
dds_sample_free_contents (addr, jsr_ops);
addr += elem_size;
}
ops += jmp ? (jmp - 3) : 2;
break;
}
}
break;
}
case DDS_OP_VAL_UNI:
{
const bool has_default = op & DDS_OP_FLAG_DEF;
subtype = DDS_OP_SUBTYPE (op);
num = ops[0];
const uint32_t * jeq_op = ops + DDS_OP_ADR_JSR (ops[1]) - 2;
uint32_t disc = 0;
assert (subtype <= DDS_OP_VAL_4BY);
#ifdef OP_DEBUG_FREE
TRACE (("F-UNI: switch %s cases %d\n", stream_op_type[subtype], num));
#endif
/* Get discriminant */
switch (subtype)
{
case DDS_OP_VAL_1BY:
{
disc = *((uint8_t*) addr);
break;
}
case DDS_OP_VAL_2BY:
{
disc = *((uint16_t*) addr);
break;
}
case DDS_OP_VAL_4BY:
{
disc = *((uint32_t*) addr);
break;
}
default: assert (0);
}
/* Free case matching discriminant */
while (num--)
{
assert ((DDS_OP_MASK & jeq_op[0]) == DDS_OP_JEQ);
if ((jeq_op[1] == disc) || (has_default && (num == 0)))
{
subtype = DDS_JEQ_TYPE (jeq_op[0]);
addr = data + jeq_op[2];
switch (subtype)
{
case DDS_OP_VAL_1BY:
case DDS_OP_VAL_2BY:
case DDS_OP_VAL_4BY:
case DDS_OP_VAL_8BY:
case DDS_OP_VAL_BST:
{
break;
}
case DDS_OP_VAL_STR:
{
dds_free (*((char**) addr));
*((char**) addr) = NULL;
break;
}
default:
{
dds_sample_free_contents (addr, jeq_op + DDS_OP_ADR_JSR (jeq_op[0]));
break;
}
}
break;
}
jeq_op += 3;
}
/* Jump to next instruction */
ops += DDS_OP_ADR_JMP (ops[1]) - 2;
break;
}
case DDS_OP_VAL_BST:
{
ops++;
break;
}
default: assert (0);
}
break;
}
case DDS_OP_JSR: /* Implies nested type */
{
#ifdef OP_DEBUG_FREE
TRACE (("F-JSR: %d\n", DDS_OP_JUMP (op)));
#endif
dds_sample_free_contents (data, ops + DDS_OP_JUMP (op));
ops++;
break;
}
default: assert (0);
}
}
#ifdef OP_DEBUG_FREE
TRACE (("F-RTS:\n"));
#endif
}
static void dds_sample_free_key (char * sample, const struct dds_topic_descriptor * desc)
{
uint32_t i;
const uint32_t * op;
for (i = 0; i < desc->m_nkeys; i++)
{
op = desc->m_ops + desc->m_keys[i].m_index;
if (DDS_OP_TYPE (*op) == DDS_OP_VAL_STR)
{
dds_free (*(char**)(sample + op[1]));
}
}
}
void dds_sample_free (void * sample, const struct dds_topic_descriptor * desc, dds_free_op_t op)
{
assert (desc);
if (sample)
{
if (op & DDS_FREE_CONTENTS_BIT)
{
dds_sample_free_contents ((char*) sample, desc->m_ops);
}
else if (op & DDS_FREE_KEY_BIT)
{
dds_sample_free_key ((char*) sample, desc);
}
if (op & DDS_FREE_ALL_BIT)
{
dds_free (sample);
}
}
}

View file

@ -0,0 +1,440 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include "ddsi/q_entity.h"
#include "ddsi/q_thread.h"
#include "ddsi/q_config.h"
#include "ddsi/q_builtin_topic.h"
#include "q__osplser.h"
#include "dds__init.h"
#include "dds__qos.h"
#include "dds__domain.h"
#include "dds__participant.h"
#include "dds__err.h"
#include "dds__types.h"
#include "dds__report.h"
#include "dds__builtin.h"
#include "dds__subscriber.h"
static dds_return_t
dds__delete_builtin_participant(
dds_entity *e);
static _Must_inspect_result_ dds_entity_t
dds__create_builtin_participant(
void);
static _Must_inspect_result_ dds_entity_t
dds__create_builtin_publisher(
_In_ dds_entity_t participant);
static _Must_inspect_result_ dds_entity_t
dds__create_builtin_writer(
_In_ dds_entity_t topic);
static _Must_inspect_result_ dds_entity_t
dds__get_builtin_participant(
void);
static os_mutex g_builtin_mutex;
static os_atomic_uint32_t m_call_count = OS_ATOMIC_UINT32_INIT(0);
/* Singletons are used to publish builtin data locally. */
static dds_entity_t g_builtin_local_participant = 0;
static dds_entity_t g_builtin_local_publisher = 0;
static dds_entity_t g_builtin_local_writers[] = {
0, /* index DDS_BUILTIN_TOPIC_DCPSPARTICIPANT - DDS_KIND_INTERNAL - 1 */
0, /* index DDS_BUILTIN_TOPIC_CMPARTICIPANT - DDS_KIND_INTERNAL - 1 */
0, /* index DDS_BUILTIN_TOPIC_DCPSTYPE - DDS_KIND_INTERNAL - 1 */
0, /* index DDS_BUILTIN_TOPIC_DCPSTOPIC - DDS_KIND_INTERNAL - 1 */
0, /* index DDS_BUILTIN_TOPIC_DCPSPUBLICATION - DDS_KIND_INTERNAL - 1 */
0, /* index DDS_BUILTIN_TOPIC_CMPUBLISHER - DDS_KIND_INTERNAL - 1 */
0, /* index DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION - DDS_KIND_INTERNAL - 1 */
0, /* index DDS_BUILTIN_TOPIC_CMSUBSCRIBER - DDS_KIND_INTERNAL - 1 */
0, /* index DDS_BUILTIN_TOPIC_CMDATAWRITER - DDS_KIND_INTERNAL - 1 */
0, /* index DDS_BUILTIN_TOPIC_CMDATAREADER - DDS_KIND_INTERNAL - 1 */
};
static dds_return_t
dds__delete_builtin_participant(
dds_entity *e)
{
struct thread_state1 * const thr = lookup_thread_state ();
const bool asleep = !vtime_awake_p (thr->vtime);
assert(e);
assert(thr);
assert(dds_entity_kind(e->m_hdl) == DDS_KIND_PARTICIPANT);
if (asleep) {
thread_state_awake(thr);
}
dds_domain_free(e->m_domain);
if (asleep) {
thread_state_asleep(thr);
}
return DDS_RETCODE_OK;
}
/*
* We don't use the 'normal' create participant.
*
* This way, the application is not able to access the local builtin writers.
* Also, we can indicate that it should be a 'local only' participant, which
* means that none of the entities under the hierarchy of this participant will
* be exposed to the outside world. This is what we want, because these builtin
* writers are only applicable to local user readers.
*/
static _Must_inspect_result_ dds_entity_t
dds__create_builtin_participant(
void)
{
int q_rc;
nn_plist_t plist;
struct thread_state1 * thr;
bool asleep;
nn_guid_t guid;
dds_entity_t participant;
dds_participant *pp;
nn_plist_init_empty (&plist);
thr = lookup_thread_state ();
asleep = !vtime_awake_p (thr->vtime);
if (asleep) {
thread_state_awake (thr);
}
q_rc = new_participant (&guid, RTPS_PF_NO_BUILTIN_WRITERS | RTPS_PF_NO_BUILTIN_READERS | RTPS_PF_ONLY_LOCAL, &plist);
if (asleep) {
thread_state_asleep (thr);
}
if (q_rc != 0) {
participant = DDS_ERRNO(DDS_RETCODE_ERROR, "Internal builtin error");
goto fail;
}
pp = dds_alloc (sizeof (*pp));
participant = dds_entity_init (&pp->m_entity, NULL, DDS_KIND_PARTICIPANT, NULL, NULL, 0);
if (participant < 0) {
goto fail;
}
pp->m_entity.m_guid = guid;
pp->m_entity.m_domain = dds_domain_create (config.domainId);
pp->m_entity.m_domainid = config.domainId;
pp->m_entity.m_deriver.delete = dds__delete_builtin_participant;
fail:
return participant;
}
static _Must_inspect_result_ dds_entity_t
dds__create_builtin_publisher(
_In_ dds_entity_t participant)
{
dds_entity_t pub;
dds_qos_t *qos;
const char *partition = "__BUILT-IN PARTITION__";
qos = dds_qos_create();
dds_qset_partition(qos, 1, &partition);
pub = dds_create_publisher(participant, qos, NULL);
dds_qos_delete(qos);
return pub;
}
static _Must_inspect_result_ dds_entity_t
dds__create_builtin_subscriber(
_In_ dds_entity *participant)
{
dds_entity_t sub;
dds_qos_t *qos;
const char *partition = "__BUILT-IN PARTITION__";
qos = dds_qos_create();
dds_qset_partition(qos, 1, &partition);
/* Create builtin-subscriber */
sub = dds__create_subscriber_l(participant, qos, NULL);
dds_qos_delete(qos);
return sub;
}
static _Must_inspect_result_ dds_entity_t
dds__create_builtin_writer(
_In_ dds_entity_t topic)
{
dds_entity_t wr;
dds_entity_t pub = dds__get_builtin_publisher();
if (pub > 0) {
dds_entity_t top = dds__get_builtin_topic(pub, topic);
if (top > 0) {
dds_qos_t *qos;
// TODO: set builtin qos
qos = dds_qos_create();
dds_qset_durability(qos, DDS_DURABILITY_TRANSIENT_LOCAL);
dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_MSECS(100));
wr = dds_create_writer(pub, top, qos, NULL);
dds_qos_delete(qos);
(void)dds_delete(top);
} else {
wr = top;
}
} else {
wr = pub;
}
return wr;
}
static _Must_inspect_result_ dds_entity_t
dds__get_builtin_participant(
void)
{
if (g_builtin_local_participant == 0) {
g_builtin_local_participant = dds__create_builtin_participant();
}
return g_builtin_local_participant;
}
_Must_inspect_result_ dds_entity_t
dds__get_builtin_publisher(
void)
{
if (g_builtin_local_publisher == 0) {
dds_entity_t par = dds__get_builtin_participant();
if (par > 0) {
g_builtin_local_publisher = dds__create_builtin_publisher(par);
}
}
return g_builtin_local_publisher;
}
_Must_inspect_result_ dds_entity_t
dds__get_builtin_subscriber(
_In_ dds_entity_t e)
{
dds_entity_t sub;
dds_return_t ret;
dds_entity_t participant;
dds_participant *p;
dds_entity *part_entity;
participant = dds_get_participant(e);
if (participant <= 0) {
/* error already in participant error; no need to repeat error */
ret = participant;
goto error;
}
ret = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, (dds_entity **)&part_entity);
if (ret != DDS_RETCODE_OK) {
goto error;
}
p = (dds_participant *)part_entity;
if(p->m_builtin_subscriber <= 0) {
p->m_builtin_subscriber = dds__create_builtin_subscriber(part_entity);
}
sub = p->m_builtin_subscriber;
dds_entity_unlock(part_entity);
return sub;
/* Error handling */
error:
assert(ret < 0);
return ret;
}
_Must_inspect_result_ dds_entity_t
dds__get_builtin_topic(
_In_ dds_entity_t e,
_In_ dds_entity_t topic)
{
dds_entity_t participant;
dds_entity_t ret;
participant = dds_get_participant(e);
if (participant > 0) {
const dds_topic_descriptor_t *desc;
const char *name;
if (topic == DDS_BUILTIN_TOPIC_DCPSPARTICIPANT) {
desc = &DDS_ParticipantBuiltinTopicData_desc;
name = "DCPSParticipant";
} else if (topic == DDS_BUILTIN_TOPIC_CMPARTICIPANT) {
desc = &DDS_CMParticipantBuiltinTopicData_desc;
name = "CMParticipant";
} else if (topic == DDS_BUILTIN_TOPIC_DCPSTYPE) {
desc = &DDS_TypeBuiltinTopicData_desc;
name = "DCPSType";
} else if (topic == DDS_BUILTIN_TOPIC_DCPSTOPIC) {
desc = &DDS_TopicBuiltinTopicData_desc;
name = "DCPSTopic";
} else if (topic == DDS_BUILTIN_TOPIC_DCPSPUBLICATION) {
desc = &DDS_PublicationBuiltinTopicData_desc;
name = "DCPSPublication";
} else if (topic == DDS_BUILTIN_TOPIC_CMPUBLISHER) {
desc = &DDS_CMPublisherBuiltinTopicData_desc;
name = "CMPublisher";
} else if (topic == DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION) {
desc = &DDS_SubscriptionBuiltinTopicData_desc;
name = "DCPSSubscription";
} else if (topic == DDS_BUILTIN_TOPIC_CMSUBSCRIBER) {
desc = &DDS_CMSubscriberBuiltinTopicData_desc;
name = "CMSubscriber";
} else if (topic == DDS_BUILTIN_TOPIC_CMDATAWRITER) {
desc = &DDS_CMDataWriterBuiltinTopicData_desc;
name = "CMDataWriter";
} else if (topic == DDS_BUILTIN_TOPIC_CMDATAREADER) {
desc = &DDS_CMDataReaderBuiltinTopicData_desc;
name = "CMDataReader";
} else {
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Invalid builtin-topic handle(%d)", topic);
goto err_invalid_topic;
}
ret = dds_find_topic(participant, name);
if (ret < 0 && dds_err_nr(ret) == DDS_RETCODE_PRECONDITION_NOT_MET) {
dds_qos_t *tqos;
/* drop the precondition-no-met error */
DDS_REPORT_FLUSH(0);
DDS_REPORT_STACK();
tqos = dds_qos_create();
dds_qset_durability(tqos, DDS_DURABILITY_TRANSIENT_LOCAL);
dds_qset_presentation(tqos, DDS_PRESENTATION_TOPIC, false, false);
dds_qset_reliability(tqos, DDS_RELIABILITY_RELIABLE, DDS_MSECS(100));
ret = dds_create_topic(participant, desc, name, tqos, NULL);
dds_qos_delete(tqos);
}
} else {
/* Failed to get participant of provided entity */
ret = participant;
}
err_invalid_topic:
return ret;
}
static _Must_inspect_result_ dds_entity_t
dds__get_builtin_writer(
_In_ dds_entity_t topic)
{
dds_entity_t wr;
if ((topic >= DDS_BUILTIN_TOPIC_DCPSPARTICIPANT) && (topic <= DDS_BUILTIN_TOPIC_CMDATAREADER)) {
int index = (int)(topic - DDS_KIND_INTERNAL - 1);
os_mutexLock(&g_builtin_mutex);
wr = g_builtin_local_writers[index];
if (wr == 0) {
wr = dds__create_builtin_writer(topic);
if (wr > 0) {
g_builtin_local_writers[index] = wr;
}
}
os_mutexUnlock(&g_builtin_mutex);
} else {
wr = DDS_ERRNO(DDS_RETCODE_ERROR, "Given topic is not a builtin topic.");
}
return wr;
}
static dds_return_t
dds__builtin_write(
_In_ dds_entity_t topic,
_In_ const void *data,
_In_ dds_time_t timestamp,
_In_ int alive)
{
dds_return_t ret = DDS_RETCODE_OK;
if (os_atomic_inc32_nv(&m_call_count) > 1) {
dds_entity_t wr;
wr = dds__get_builtin_writer(topic);
if (wr > 0) {
if (alive) {
ret = dds_write_ts(wr, data, timestamp);
} else {
ret = dds_dispose_ts(wr, data, timestamp);
}
} else {
ret = wr;
}
}
os_atomic_dec32(&m_call_count);
return ret;
}
void
dds__builtin_init(
void)
{
assert(os_atomic_ld32(&m_call_count) == 0);
os_mutexInit(&g_builtin_mutex);
os_atomic_inc32(&m_call_count);
}
void
dds__builtin_fini(
void)
{
assert(os_atomic_ld32(&m_call_count) > 0);
while (os_atomic_dec32_nv(&m_call_count) > 0) {
os_atomic_inc32_nv(&m_call_count);
dds_sleepfor(DDS_MSECS(10));
}
(void)dds_delete(g_builtin_local_participant);
g_builtin_local_participant = 0;
g_builtin_local_publisher = 0;
memset(g_builtin_local_writers, 0, sizeof(g_builtin_local_writers));
os_mutexDestroy(&g_builtin_mutex);
}
void
forward_builtin_participant(
_In_ DDS_ParticipantBuiltinTopicData *data,
_In_ nn_wctime_t timestamp,
_In_ int alive)
{
dds_return_t ret;
DDS_REPORT_STACK();
ret = dds__builtin_write(DDS_BUILTIN_TOPIC_DCPSPARTICIPANT, data, timestamp.v, alive);
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
}
void
forward_builtin_cmparticipant(
_In_ DDS_CMParticipantBuiltinTopicData *data,
_In_ nn_wctime_t timestamp,
_In_ int alive)
{
dds_return_t ret;
DDS_REPORT_STACK();
ret = dds__builtin_write(DDS_BUILTIN_TOPIC_CMPARTICIPANT, data, timestamp.v, alive);
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
}

View file

@ -0,0 +1,371 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef OSPL_DDS_BUILTINTOPICS_IDL
#define OSPL_DDS_BUILTINTOPICS_IDL
/*
This file was the one orginally in ./src/api/dcps/saj/code/.
(and therefore by implication ./src/api/dcps/cj/java/code).
*/
#define BUILTIN_TOPIC_KEY_TYPE_NATIVE long
module DDS {
// Added octet sequence definition.
// Prevents IDL compiler warnings from deprecated anonymous types
// on composite type members.
typedef sequence<octet> octSeq;
typedef BUILTIN_TOPIC_KEY_TYPE_NATIVE BuiltinTopicKey_t[3];
typedef sequence<string> StringSeq;
typedef short DataRepresentationId_t;
const DataRepresentationId_t XCDR_REPRESENTATION = 0;
const DataRepresentationId_t XML_REPRESENTATION = 0x001;
const DataRepresentationId_t OSPL_REPRESENTATION = 0x400;
const DataRepresentationId_t GPB_REPRESENTATION = 0x401;
const DataRepresentationId_t INVALID_REPRESENTATION = 0x7FFF;
struct Duration_t {
long sec;
unsigned long nanosec;
};
struct UserDataQosPolicy {
octSeq value;
// replaced deprecated anonymous sequence<octet> value;
};
struct TopicDataQosPolicy {
octSeq value;
// replaced deprecated anonymous sequence<octet> value;
};
struct GroupDataQosPolicy {
octSeq value;
// replaced deprected anonymous sequence<octet> value;
};
struct TransportPriorityQosPolicy {
long value;
};
struct LifespanQosPolicy {
Duration_t duration;
};
enum DurabilityQosPolicyKind {
VOLATILE_DURABILITY_QOS,
TRANSIENT_LOCAL_DURABILITY_QOS,
TRANSIENT_DURABILITY_QOS,
PERSISTENT_DURABILITY_QOS
};
struct DurabilityQosPolicy {
DurabilityQosPolicyKind kind;
};
enum PresentationQosPolicyAccessScopeKind {
INSTANCE_PRESENTATION_QOS,
TOPIC_PRESENTATION_QOS,
GROUP_PRESENTATION_QOS
};
struct PresentationQosPolicy {
PresentationQosPolicyAccessScopeKind access_scope;
boolean coherent_access;
boolean ordered_access;
};
struct DeadlineQosPolicy {
Duration_t period;
};
struct LatencyBudgetQosPolicy {
Duration_t duration;
};
enum OwnershipQosPolicyKind {
SHARED_OWNERSHIP_QOS,
EXCLUSIVE_OWNERSHIP_QOS
};
struct OwnershipQosPolicy {
OwnershipQosPolicyKind kind;
};
struct OwnershipStrengthQosPolicy {
long value;
};
enum LivelinessQosPolicyKind {
AUTOMATIC_LIVELINESS_QOS,
MANUAL_BY_PARTICIPANT_LIVELINESS_QOS,
MANUAL_BY_TOPIC_LIVELINESS_QOS
};
struct LivelinessQosPolicy {
LivelinessQosPolicyKind kind;
Duration_t lease_duration;
};
struct TimeBasedFilterQosPolicy {
Duration_t minimum_separation;
};
struct PartitionQosPolicy {
StringSeq name;
};
enum ReliabilityQosPolicyKind {
BEST_EFFORT_RELIABILITY_QOS,
RELIABLE_RELIABILITY_QOS
};
struct ReliabilityQosPolicy {
ReliabilityQosPolicyKind kind;
Duration_t max_blocking_time;
boolean synchronous;
};
enum DestinationOrderQosPolicyKind {
BY_RECEPTION_TIMESTAMP_DESTINATIONORDER_QOS,
BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS
};
struct DestinationOrderQosPolicy {
DestinationOrderQosPolicyKind kind;
};
enum HistoryQosPolicyKind {
KEEP_LAST_HISTORY_QOS,
KEEP_ALL_HISTORY_QOS
};
struct HistoryQosPolicy {
HistoryQosPolicyKind kind;
long depth;
};
struct ResourceLimitsQosPolicy {
long max_samples;
long max_instances;
long max_samples_per_instance;
};
struct DurabilityServiceQosPolicy {
Duration_t service_cleanup_delay;
HistoryQosPolicyKind history_kind;
long history_depth;
long max_samples;
long max_instances;
long max_samples_per_instance;
};
struct ProductDataQosPolicy {
string value;
};
struct EntityFactoryQosPolicy {
boolean autoenable_created_entities;
};
struct ShareQosPolicy {
string name;
boolean enable;
};
struct WriterDataLifecycleQosPolicy {
boolean autodispose_unregistered_instances;
Duration_t autopurge_suspended_samples_delay;
Duration_t autounregister_instance_delay;
};
enum InvalidSampleVisibilityQosPolicyKind {
NO_INVALID_SAMPLES,
MINIMUM_INVALID_SAMPLES,
ALL_INVALID_SAMPLES
};
struct InvalidSampleVisibilityQosPolicy {
InvalidSampleVisibilityQosPolicyKind kind;
};
// @discrepancy The below QoS did not exist in ./etc/idlpp/dds_dcps.idl Retain ?
struct SubscriptionKeyQosPolicy {
boolean use_key_list;
StringSeq key_list;
};
// @discrepancy End of above discrepancy
struct ReaderDataLifecycleQosPolicy {
Duration_t autopurge_nowriter_samples_delay;
Duration_t autopurge_disposed_samples_delay;
boolean autopurge_dispose_all;
// @discrepancy The below member existed in this file but did not
// in ./etc/idlpp/dds_dcps.idl. Retain ?
boolean enable_invalid_samples; // @deprecated Will be replaced by invalid_sample_visibility in due time
InvalidSampleVisibilityQosPolicy invalid_sample_visibility;
};
struct UserKeyQosPolicy {
boolean enable;
string expression;
};
struct ReaderLifespanQosPolicy {
boolean use_lifespan;
Duration_t duration;
};
struct TypeHash {
unsigned long long msb;
unsigned long long lsb;
};
struct ParticipantBuiltinTopicData {
BuiltinTopicKey_t key;
UserDataQosPolicy user_data;
};
#pragma keylist ParticipantBuiltinTopicData key
struct TopicBuiltinTopicData {
BuiltinTopicKey_t key;
string name;
string type_name;
DurabilityQosPolicy durability;
DurabilityServiceQosPolicy durability_service;
DeadlineQosPolicy deadline;
LatencyBudgetQosPolicy latency_budget;
LivelinessQosPolicy liveliness;
ReliabilityQosPolicy reliability;
TransportPriorityQosPolicy transport_priority;
LifespanQosPolicy lifespan;
DestinationOrderQosPolicy destination_order;
HistoryQosPolicy history;
ResourceLimitsQosPolicy resource_limits;
OwnershipQosPolicy ownership;
TopicDataQosPolicy topic_data;
};
#pragma keylist TopicBuiltinTopicData key
struct TypeBuiltinTopicData {
string name;
DataRepresentationId_t data_representation_id;
TypeHash type_hash;
octSeq meta_data;
octSeq extentions;
};
#pragma keylist TypeBuiltinTopicData name data_representation_id type_hash.msb type_hash.lsb
struct PublicationBuiltinTopicData {
BuiltinTopicKey_t key;
BuiltinTopicKey_t participant_key;
string topic_name;
string type_name;
DurabilityQosPolicy durability;
DeadlineQosPolicy deadline;
LatencyBudgetQosPolicy latency_budget;
LivelinessQosPolicy liveliness;
ReliabilityQosPolicy reliability;
LifespanQosPolicy lifespan;
DestinationOrderQosPolicy destination_order;
UserDataQosPolicy user_data;
OwnershipQosPolicy ownership;
OwnershipStrengthQosPolicy ownership_strength;
PresentationQosPolicy presentation;
PartitionQosPolicy partition;
TopicDataQosPolicy topic_data;
GroupDataQosPolicy group_data;
};
#pragma keylist PublicationBuiltinTopicData key
struct SubscriptionBuiltinTopicData {
BuiltinTopicKey_t key;
BuiltinTopicKey_t participant_key;
string topic_name;
string type_name;
DurabilityQosPolicy durability;
DeadlineQosPolicy deadline;
LatencyBudgetQosPolicy latency_budget;
LivelinessQosPolicy liveliness;
ReliabilityQosPolicy reliability;
OwnershipQosPolicy ownership;
DestinationOrderQosPolicy destination_order;
UserDataQosPolicy user_data;
TimeBasedFilterQosPolicy time_based_filter;
PresentationQosPolicy presentation;
PartitionQosPolicy partition;
TopicDataQosPolicy topic_data;
GroupDataQosPolicy group_data;
};
#pragma keylist SubscriptionBuiltinTopicData key
struct CMParticipantBuiltinTopicData {
BuiltinTopicKey_t key;
ProductDataQosPolicy product;
};
#pragma keylist CMParticipantBuiltinTopicData key
struct CMPublisherBuiltinTopicData {
BuiltinTopicKey_t key;
ProductDataQosPolicy product;
BuiltinTopicKey_t participant_key;
string name;
EntityFactoryQosPolicy entity_factory;
PartitionQosPolicy partition;
};
#pragma keylist CMPublisherBuiltinTopicData key
struct CMSubscriberBuiltinTopicData {
BuiltinTopicKey_t key;
ProductDataQosPolicy product;
BuiltinTopicKey_t participant_key;
string name;
EntityFactoryQosPolicy entity_factory;
ShareQosPolicy share;
PartitionQosPolicy partition;
};
#pragma keylist CMSubscriberBuiltinTopicData key
struct CMDataWriterBuiltinTopicData {
BuiltinTopicKey_t key;
ProductDataQosPolicy product;
BuiltinTopicKey_t publisher_key;
string name;
HistoryQosPolicy history;
ResourceLimitsQosPolicy resource_limits;
WriterDataLifecycleQosPolicy writer_data_lifecycle;
};
#pragma keylist CMDataWriterBuiltinTopicData key
struct CMDataReaderBuiltinTopicData {
BuiltinTopicKey_t key;
ProductDataQosPolicy product;
BuiltinTopicKey_t subscriber_key;
string name;
HistoryQosPolicy history;
ResourceLimitsQosPolicy resource_limits;
ReaderDataLifecycleQosPolicy reader_data_lifecycle;
UserKeyQosPolicy subscription_keys;
ReaderLifespanQosPolicy reader_lifespan;
ShareQosPolicy share;
};
#pragma keylist CMDataReaderBuiltinTopicData key
};
#endif /* OSPL_DDS_BUILTINTOPICS_IDL */

View file

@ -0,0 +1,79 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include "ddsc/dds.h"
#include "dds__entity.h"
#include "dds__subscriber.h"
#include "dds__publisher.h"
#include "dds__err.h"
#include "dds__report.h"
_Pre_satisfies_(((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) || \
((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_SUBSCRIBER) || \
((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER ) || \
((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_SUBSCRIBER) )
dds_return_t
dds_begin_coherent(
_In_ dds_entity_t entity)
{
dds_return_t ret;
switch(dds_entity_kind(entity)) {
case DDS_KIND_READER:
case DDS_KIND_WRITER:
/* Invoking on a writer/reader behaves as if invoked on
* its parent publisher/subscriber. */
ret = dds_begin_coherent(dds_get_parent(entity));
break;
case DDS_KIND_PUBLISHER:
ret = dds_publisher_begin_coherent(entity);
break;
case DDS_KIND_SUBSCRIBER:
ret = dds_subscriber_begin_coherent(entity);
break;
default:
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Given entity can not control coherency");
break;
}
return ret;
}
_Pre_satisfies_(((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) || \
((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_SUBSCRIBER) || \
((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER ) || \
((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_SUBSCRIBER) )
dds_return_t
dds_end_coherent(
_In_ dds_entity_t entity)
{
dds_return_t ret;
switch(dds_entity_kind(entity)) {
case DDS_KIND_READER:
case DDS_KIND_WRITER:
/* Invoking on a writer/reader behaves as if invoked on
* its parent publisher/subscriber. */
ret = dds_end_coherent(dds_get_parent(entity));
break;
case DDS_KIND_PUBLISHER:
ret = dds_publisher_end_coherent(entity);
break;
case DDS_KIND_SUBSCRIBER:
ret = dds_subscriber_end_coherent(entity);
break;
default:
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Given entity can not control coherency");
break;
}
return ret;
}

View file

@ -0,0 +1,130 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef OSPL_DDS_DCPS_BUILTINTOPICS_IDL
#define OSPL_DDS_DCPS_BUILTINTOPICS_IDL
/**
*This file (name) was orginally in ./src/api/dcps/ccpp/idl/.
*It's been modified to include from another file the base definitions
*required for this 'built in topics' superset... :
*/
#include "dds_builtinTopics.idl"
module DDS {
struct Time_t {
long sec;
unsigned long nanosec;
};
enum SchedulingClassQosPolicyKind {
SCHEDULE_DEFAULT,
SCHEDULE_TIMESHARING,
SCHEDULE_REALTIME
};
struct SchedulingClassQosPolicy {
SchedulingClassQosPolicyKind kind;
};
enum SchedulingPriorityQosPolicyKind {
PRIORITY_RELATIVE,
PRIORITY_ABSOLUTE
};
struct SchedulingPriorityQosPolicy {
SchedulingPriorityQosPolicyKind kind;
};
struct SchedulingQosPolicy {
SchedulingClassQosPolicy scheduling_class;
SchedulingPriorityQosPolicy scheduling_priority_kind;
long scheduling_priority;
};
struct DomainParticipantQos {
UserDataQosPolicy user_data;
EntityFactoryQosPolicy entity_factory;
SchedulingQosPolicy watchdog_scheduling;
SchedulingQosPolicy listener_scheduling;
};
struct TopicQos {
TopicDataQosPolicy topic_data;
DurabilityQosPolicy durability;
DurabilityServiceQosPolicy durability_service;
DeadlineQosPolicy deadline;
LatencyBudgetQosPolicy latency_budget;
LivelinessQosPolicy liveliness;
ReliabilityQosPolicy reliability;
DestinationOrderQosPolicy destination_order;
HistoryQosPolicy history;
ResourceLimitsQosPolicy resource_limits;
TransportPriorityQosPolicy transport_priority;
LifespanQosPolicy lifespan;
OwnershipQosPolicy ownership;
};
struct DataWriterQos {
DurabilityQosPolicy durability;
DeadlineQosPolicy deadline;
LatencyBudgetQosPolicy latency_budget;
LivelinessQosPolicy liveliness;
ReliabilityQosPolicy reliability;
DestinationOrderQosPolicy destination_order;
HistoryQosPolicy history;
ResourceLimitsQosPolicy resource_limits;
TransportPriorityQosPolicy transport_priority;
LifespanQosPolicy lifespan;
UserDataQosPolicy user_data;
OwnershipQosPolicy ownership;
OwnershipStrengthQosPolicy ownership_strength;
WriterDataLifecycleQosPolicy writer_data_lifecycle;
};
struct PublisherQos {
PresentationQosPolicy presentation;
PartitionQosPolicy partition;
GroupDataQosPolicy group_data;
EntityFactoryQosPolicy entity_factory;
};
struct DataReaderQos {
DurabilityQosPolicy durability;
DeadlineQosPolicy deadline;
LatencyBudgetQosPolicy latency_budget;
LivelinessQosPolicy liveliness;
ReliabilityQosPolicy reliability;
DestinationOrderQosPolicy destination_order;
HistoryQosPolicy history;
ResourceLimitsQosPolicy resource_limits;
UserDataQosPolicy user_data;
OwnershipQosPolicy ownership;
TimeBasedFilterQosPolicy time_based_filter;
ReaderDataLifecycleQosPolicy reader_data_lifecycle;
SubscriptionKeyQosPolicy subscription_keys;
ReaderLifespanQosPolicy reader_lifespan;
ShareQosPolicy share;
};
struct SubscriberQos {
PresentationQosPolicy presentation;
PartitionQosPolicy partition;
GroupDataQosPolicy group_data;
EntityFactoryQosPolicy entity_factory;
ShareQosPolicy share;
};
};
#endif /* DDS_DCPS_BUILTINTOPICS_IDL */

View file

@ -0,0 +1,59 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "dds__domain.h"
#include "dds__tkmap.h"
static int dds_domain_compare (const int32_t * a, const int32_t * b)
{
return (*a == *b) ? 0 : (*a < *b) ? -1 : 1;
}
const ut_avlTreedef_t dds_domaintree_def = UT_AVL_TREEDEF_INITIALIZER
(
offsetof (dds_domain, m_node),
offsetof (dds_domain, m_id),
(int (*) (const void *, const void *)) dds_domain_compare,
0
);
dds_domain * dds_domain_find_locked (dds_domainid_t id)
{
return (dds_domain*) ut_avlLookup (&dds_domaintree_def, &dds_global.m_domains, &id);
}
dds_domain * dds_domain_create (dds_domainid_t id)
{
dds_domain * domain;
os_mutexLock (&dds_global.m_mutex);
domain = dds_domain_find_locked (id);
if (domain == NULL)
{
domain = dds_alloc (sizeof (*domain));
domain->m_id = id;
ut_avlInit (&dds_topictree_def, &domain->m_topics);
ut_avlInsert (&dds_domaintree_def, &dds_global.m_domains, domain);
}
domain->m_refc++;
os_mutexUnlock (&dds_global.m_mutex);
return domain;
}
void dds_domain_free (dds_domain * domain)
{
os_mutexLock (&dds_global.m_mutex);
if (--domain->m_refc == 0)
{
ut_avlDelete (&dds_domaintree_def, &dds_global.m_domains, domain);
dds_free (domain);
}
os_mutexUnlock (&dds_global.m_mutex);
}

File diff suppressed because it is too large Load diff

102
src/core/ddsc/src/dds_err.c Normal file
View file

@ -0,0 +1,102 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <stdlib.h>
#include "os/os.h"
#include "dds__types.h"
#include "dds__err.h"
#define DDS_ERR_CODE_NUM 12
#define DDS_ERR_MSG_MAX 128
#define DDS_ERR_NR_INDEX(e) (((-e) & DDS_ERR_NR_MASK) -1)
static const char * dds_err_code_array[DDS_ERR_CODE_NUM] =
{
"Error",
"Unsupported",
"Bad Parameter",
"Precondition Not Met",
"Out Of Resources",
"Not Enabled",
"Immutable Policy",
"Inconsistent Policy",
"Already Deleted",
"Timeout",
"No Data",
"Illegal Operation"
};
const char * dds_err_str (dds_return_t err)
{
unsigned index = DDS_ERR_NR_INDEX (err);
if (err >= 0)
{
return "Success";
}
if (index >= DDS_ERR_CODE_NUM)
{
return "Unknown";
}
return dds_err_code_array[index];
}
bool dds_err_check (dds_return_t err, unsigned flags, const char * where)
{
if (err < 0)
{
if (flags & (DDS_CHECK_REPORT | DDS_CHECK_FAIL))
{
char msg[DDS_ERR_MSG_MAX];
(void) snprintf (msg, DDS_ERR_MSG_MAX, "Error %d:M%d:%s", dds_err_file_id(err), dds_err_line(err), dds_err_str(err));
if (flags & DDS_CHECK_REPORT)
{
printf ("%s: %s\n", where, msg);
}
if (flags & DDS_CHECK_FAIL)
{
dds_fail (msg, where);
}
}
if (flags & DDS_CHECK_EXIT)
{
exit (-1);
}
}
return (err >= 0);
}
static void dds_fail_default (const char * msg, const char * where)
{
fprintf (stderr, "Aborting Failure: %s %s\n", where, msg);
abort ();
}
static dds_fail_fn dds_fail_func = dds_fail_default;
void dds_fail_set (dds_fail_fn fn)
{
dds_fail_func = fn;
}
dds_fail_fn dds_fail_get (void)
{
return dds_fail_func;
}
void dds_fail (const char * msg, const char * where)
{
if (dds_fail_func)
{
(dds_fail_func) (msg, where);
}
}

View file

@ -0,0 +1,79 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "dds__iid.h"
#include "ddsi/q_time.h"
#include "ddsi/q_globals.h"
static os_mutex dds_iid_lock_g;
static dds_iid dds_iid_g;
static void dds_tea_encrypt (uint32_t v[2], const uint32_t k[4])
{
/* TEA encryption straight from Wikipedia */
uint32_t v0=v[0], v1=v[1], sum=0, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i < 32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
} /* end cycle */
v[0]=v0; v[1]=v1;
}
static void dds_tea_decrypt (uint32_t v[2], const uint32_t k[4])
{
uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i<32; i++) { /* basic cycle start */
v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
sum -= delta;
} /* end cycle */
v[0]=v0; v[1]=v1;
}
uint64_t dds_iid_gen (void)
{
uint64_t iid;
union { uint64_t u64; uint32_t u32[2]; } tmp;
os_mutexLock (&dds_iid_lock_g);
tmp.u64 = ++dds_iid_g.counter;
dds_tea_encrypt (tmp.u32, dds_iid_g.key);
iid = tmp.u64;
os_mutexUnlock (&dds_iid_lock_g);
return iid;
}
void dds_iid_init (void)
{
union { uint64_t u64; uint32_t u32[2]; } tmp;
nn_wctime_t tnow = now ();
os_mutexInit (&dds_iid_lock_g);
dds_iid_g.key[0] = (uint32_t) ((uintptr_t) &dds_iid_g);
dds_iid_g.key[1] = (uint32_t) tnow.v;
dds_iid_g.key[2] = (uint32_t) (tnow.v >> 32);
dds_iid_g.key[3] = 0xdeadbeef;
tmp.u64 = 0;
dds_tea_decrypt (tmp.u32, dds_iid_g.key);
dds_iid_g.counter = tmp.u64;
}
void dds_iid_fini (void)
{
os_mutexDestroy (&dds_iid_lock_g);
}

View file

@ -0,0 +1,305 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <os/os.h>
#include <os/os_report.h>
#include "dds__init.h"
#include "dds__rhc.h"
#include "dds__tkmap.h"
#include "dds__iid.h"
#include "dds__domain.h"
#include "dds__err.h"
#include "dds__builtin.h"
#include "dds__report.h"
#include "ddsi/ddsi_ser.h"
#include "ddsi/q_servicelease.h"
#include "ddsi/q_entity.h"
#include <ddsi/q_config.h>
#include "ddsc/ddsc_project.h"
#ifdef _WRS_KERNEL
char *os_environ[] = { NULL };
#endif
#define DOMAIN_ID_MIN 0
#define DOMAIN_ID_MAX 230
struct q_globals gv;
dds_globals dds_global =
{
DDS_DOMAIN_DEFAULT, 0,
NULL, NULL, NULL, NULL
};
static struct cfgst * dds_cfgst = NULL;
os_mutex dds__init_mutex;
static void
dds__fini_once(void)
{
os_mutexDestroy(&dds__init_mutex);
os_osExit();
}
static void
dds__init_once(void)
{
os_osInit();
os_mutexInit(&dds__init_mutex);
os_procAtExit(dds__fini_once);
}
void
dds__startup(void)
{
static os_once_t dds__init_control = OS_ONCE_T_STATIC_INIT;
os_once(&dds__init_control, dds__init_once);
}
dds_return_t
dds_init(void)
{
dds_return_t ret = DDS_RETCODE_OK;
const char * uri;
char progname[50];
char hostname[64];
uint32_t len;
/* Be sure the DDS lifecycle resources are initialized. */
dds__startup();
DDS_REPORT_STACK();
os_mutexLock(&dds__init_mutex);
dds_global.m_init_count++;
if (dds_global.m_init_count > 1)
{
goto skip;
}
if (ut_handleserver_init() != UT_HANDLE_OK)
{
ret = DDS_ERRNO(DDS_RETCODE_ERROR, "Failed to initialize internal handle server");
goto fail_handleserver;
}
gv.tstart = now ();
gv.exception = false;
gv.static_logbuf_lock_inited = 0;
logbuf_init (&gv.static_logbuf);
os_mutexInit (&gv.static_logbuf_lock);
gv.static_logbuf_lock_inited = 1;
os_mutexInit (&dds_global.m_mutex);
uri = os_getenv (DDSC_PROJECT_NAME_NOSPACE_CAPS"_URI");
dds_cfgst = config_init (uri);
if (dds_cfgst == NULL)
{
ret = DDS_ERRNO(DDS_RETCODE_ERROR, "Failed to parse configuration XML file %s", uri);
goto fail_config;
}
/* The config.domainId can change internally in DDSI. So, remember what the
* main configured domain id is. */
dds_global.m_default_domain = config.domainId;
dds__builtin_init();
if (rtps_config_prep(dds_cfgst) != 0)
{
ret = DDS_ERRNO(DDS_RETCODE_ERROR, "Failed to configure RTPS.");
goto fail_rtps_config;
}
ut_avlInit(&dds_domaintree_def, &dds_global.m_domains);
/* Start monitoring the liveliness of all threads and renewing the
service lease if everything seems well. */
gv.servicelease = nn_servicelease_new(0, 0);
if (gv.servicelease == NULL)
{
ret = DDS_ERRNO(DDS_RETCODE_OUT_OF_RESOURCES, "Failed to create a servicelease.");
goto fail_servicelease_new;
}
if (nn_servicelease_start_renewing(gv.servicelease) < 0)
{
ret = DDS_ERRNO(DDS_RETCODE_ERROR, "Failed to start the servicelease.");
goto fail_servicelease_start;
}
if (rtps_init() < 0)
{
ret = DDS_ERRNO(DDS_RETCODE_ERROR, "Failed to initialize RTPS.");
goto fail_rtps_init;
}
upgrade_main_thread();
/* Set additional default participant properties */
gv.default_plist_pp.process_id = (unsigned)os_procIdSelf();
gv.default_plist_pp.present |= PP_PRISMTECH_PROCESS_ID;
if (os_procName(progname, sizeof(progname)) > 0)
{
gv.default_plist_pp.exec_name = dds_string_dup(progname);
}
else
{
gv.default_plist_pp.exec_name = dds_string_alloc(32);
(void) snprintf(gv.default_plist_pp.exec_name, 32, "%s: %u", DDSC_PROJECT_NAME, gv.default_plist_pp.process_id);
}
len = (uint32_t) (13 + strlen(gv.default_plist_pp.exec_name));
gv.default_plist_pp.present |= PP_PRISMTECH_EXEC_NAME;
if (os_gethostname(hostname, sizeof(hostname)) == os_resultSuccess)
{
gv.default_plist_pp.node_name = dds_string_dup(hostname);
gv.default_plist_pp.present |= PP_PRISMTECH_NODE_NAME;
}
gv.default_plist_pp.entity_name = dds_alloc(len);
(void) snprintf(gv.default_plist_pp.entity_name, len, "%s<%u>", progname,
gv.default_plist_pp.process_id);
gv.default_plist_pp.present |= PP_ENTITY_NAME;
skip:
os_mutexUnlock(&dds__init_mutex);
DDS_REPORT_FLUSH(false);
return DDS_RETCODE_OK;
fail_rtps_init:
fail_servicelease_start:
nn_servicelease_free (gv.servicelease);
gv.servicelease = NULL;
fail_servicelease_new:
thread_states_fini();
fail_rtps_config:
dds__builtin_fini();
dds_global.m_default_domain = DDS_DOMAIN_DEFAULT;
config_fini (dds_cfgst);
dds_cfgst = NULL;
fail_config:
gv.static_logbuf_lock_inited = 0;
os_mutexDestroy (&gv.static_logbuf_lock);
os_mutexDestroy (&dds_global.m_mutex);
ut_handleserver_fini();
fail_handleserver:
dds_global.m_init_count--;
os_mutexUnlock(&dds__init_mutex);
DDS_REPORT_FLUSH(true);
return ret;
}
extern void dds_fini (void)
{
os_mutexLock(&dds__init_mutex);
assert(dds_global.m_init_count > 0);
dds_global.m_init_count--;
if (dds_global.m_init_count == 0)
{
dds__builtin_fini();
ut_handleserver_fini();
rtps_term ();
nn_servicelease_free (gv.servicelease);
gv.servicelease = NULL;
downgrade_main_thread ();
thread_states_fini ();
config_fini (dds_cfgst);
dds_cfgst = NULL;
os_mutexDestroy (&gv.static_logbuf_lock);
os_mutexDestroy (&dds_global.m_mutex);
dds_global.m_default_domain = DDS_DOMAIN_DEFAULT;
}
os_mutexUnlock(&dds__init_mutex);
}
static int dds__init_plugin (void)
{
os_mutexInit (&gv.attach_lock);
dds_iid_init ();
if (dds_global.m_dur_init) (dds_global.m_dur_init) ();
return 0;
}
static void dds__fini_plugin (void)
{
os_mutexDestroy (&gv.attach_lock);
if (dds_global.m_dur_fini) (dds_global.m_dur_fini) ();
dds_iid_fini ();
}
void ddsi_plugin_init (void)
{
/* Register initialization/clean functions */
ddsi_plugin.init_fn = dds__init_plugin;
ddsi_plugin.fini_fn = dds__fini_plugin;
/* Register read cache functions */
ddsi_plugin.rhc_free_fn = dds_rhc_free;
ddsi_plugin.rhc_fini_fn = dds_rhc_fini;
ddsi_plugin.rhc_store_fn = dds_rhc_store;
ddsi_plugin.rhc_unregister_wr_fn = dds_rhc_unregister_wr;
ddsi_plugin.rhc_relinquish_ownership_fn = dds_rhc_relinquish_ownership;
ddsi_plugin.rhc_set_qos_fn = dds_rhc_set_qos;
ddsi_plugin.rhc_lookup_fn = dds_tkmap_lookup_instance_ref;
ddsi_plugin.rhc_unref_fn = dds_tkmap_instance_unref;
/* Register iid generator */
ddsi_plugin.iidgen_fn = dds_iid_gen;
}
//provides explicit default domain id.
dds_domainid_t dds_domain_default (void)
{
return dds_global.m_default_domain;
}
dds_return_t
dds__check_domain(
_In_ dds_domainid_t domain)
{
dds_return_t ret = DDS_RETCODE_OK;
/* If domain is default: use configured id. */
if (domain != DDS_DOMAIN_DEFAULT)
{
/* Specific domain has to be the same as the configured domain. */
if (domain != dds_global.m_default_domain)
{
ret = DDS_ERRNO(DDS_RETCODE_ERROR,
"Inconsistent domain configuration detected: domain on configuration: %d, domain %d",
dds_global.m_default_domain, domain);
}
}
return ret;
}

View file

@ -0,0 +1,468 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include "ddsc/dds.h"
#include "dds__entity.h"
#include "dds__write.h"
#include "dds__writer.h"
#include "dds__rhc.h"
#include "dds__tkmap.h"
#include "dds__err.h"
#include "ddsi/ddsi_ser.h"
#include "ddsi/q_entity.h"
#include "ddsi/q_thread.h"
#include "q__osplser.h"
#include "dds__report.h"
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
dds_return_t
dds_writedispose(
_In_ dds_entity_t writer,
_In_ const void *data)
{
dds_return_t ret;
DDS_REPORT_STACK();
ret = dds_writedispose_ts(writer, data, dds_time());
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK );
return ret;
}
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
dds_return_t
dds_dispose(
_In_ dds_entity_t writer,
_In_ const void *data)
{
dds_return_t ret;
DDS_REPORT_STACK();
ret = dds_dispose_ts(writer, data, dds_time());
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK );
return ret;
}
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
dds_return_t
dds_dispose_ih(
_In_ dds_entity_t writer,
_In_ dds_instance_handle_t handle)
{
dds_return_t ret;
DDS_REPORT_STACK();
ret = dds_dispose_ih_ts(writer, handle, dds_time());
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK );
return ret;
}
static struct tkmap_instance*
dds_instance_find(
_In_ const dds_topic *topic,
_In_ const void *data,
_In_ const bool create)
{
serdata_t sd = serialize_key (gv.serpool, topic->m_stopic, data);
struct tkmap_instance * inst = dds_tkmap_find (topic, sd, false, create);
ddsi_serdata_unref (sd);
return inst;
}
static void
dds_instance_remove(
_In_ const dds_topic *topic,
_In_opt_ const void *data,
_In_ dds_instance_handle_t handle)
{
struct tkmap_instance * inst;
if (handle != DDS_HANDLE_NIL) {
inst = dds_tkmap_find_by_id (gv.m_tkmap, handle);
} else {
assert (data);
inst = dds_instance_find (topic, data, false);
}
if (inst) {
struct thread_state1 * const thr = lookup_thread_state();
const bool asleep = thr ? !vtime_awake_p(thr->vtime) : false;
if (asleep) {
thread_state_awake(thr);
}
dds_tkmap_instance_unref (inst);
if (asleep) {
thread_state_asleep(thr);
}
}
}
static const dds_topic*
dds_instance_info(
_In_ dds_entity *e)
{
const dds_topic *topic = NULL;
assert (e);
assert ((dds_entity_kind(e->m_hdl) == DDS_KIND_READER) || (dds_entity_kind(e->m_hdl) == DDS_KIND_WRITER));
if (dds_entity_kind(e->m_hdl) == DDS_KIND_READER) {
topic = ((dds_reader*)e)->m_topic;
} else {
topic = ((dds_writer*)e)->m_topic;
}
return topic;
}
static const dds_topic * dds_instance_info_by_hdl (dds_entity_t e)
{
const dds_topic * topic = NULL;
dds__retcode_t rc;
dds_entity *w_or_r;
rc = dds_entity_lock(e, DDS_KIND_WRITER, &w_or_r);
if (rc == DDS_RETCODE_ILLEGAL_OPERATION) {
rc = dds_entity_lock(e, DDS_KIND_READER, &w_or_r);
}
if (rc == DDS_RETCODE_OK) {
topic = dds_instance_info(w_or_r);
dds_entity_unlock(w_or_r);
}
else {
DDS_ERROR(rc, "Error occurred on locking entity");
}
return topic;
}
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
dds_return_t
dds_register_instance(
_In_ dds_entity_t writer,
_Out_ dds_instance_handle_t *handle,
_In_ const void *data)
{
struct tkmap_instance * inst;
dds_entity *wr;
dds_return_t ret;
dds__retcode_t rc;
DDS_REPORT_STACK();
if(data == NULL){
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument data is NULL");
goto err;
}
if(handle == NULL){
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument handle is NULL");
goto err;
}
rc = dds_entity_lock(writer, DDS_KIND_WRITER, &wr);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking writer");
goto err;
}
inst = dds_instance_find (((dds_writer*) wr)->m_topic, data, true);
if(inst != NULL){
*handle = inst->m_iid;
ret = DDS_RETCODE_OK;
} else{
ret = DDS_ERRNO(DDS_RETCODE_ERROR, "Unable to create instance");
}
dds_entity_unlock(wr);
err:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
dds_return_t
dds_unregister_instance(
_In_ dds_entity_t writer,
_In_opt_ const void *data)
{
dds_return_t ret;
DDS_REPORT_STACK();
ret = dds_unregister_instance_ts (writer, data, dds_time());
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK );
return ret;
}
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
dds_return_t
dds_unregister_instance_ih(
_In_ dds_entity_t writer,
_In_opt_ dds_instance_handle_t handle)
{
dds_return_t ret;
DDS_REPORT_STACK();
ret = dds_unregister_instance_ih_ts(writer, handle, dds_time());
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK );
return ret;
}
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
dds_return_t
dds_unregister_instance_ts(
_In_ dds_entity_t writer,
_In_opt_ const void *data,
_In_ dds_time_t timestamp)
{
dds_return_t ret = DDS_RETCODE_OK;
dds__retcode_t rc;
bool autodispose = true;
dds_write_action action = DDS_WR_ACTION_UNREGISTER;
void * sample = (void*) data;
dds_entity *wr;
DDS_REPORT_STACK();
if (data == NULL){
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument data is NULL");
goto err;
}
if(timestamp < 0){
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument timestamp has negative value");
goto err;
}
rc = dds_entity_lock(writer, DDS_KIND_WRITER, &wr);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking writer");
goto err;
}
if (wr->m_qos) {
dds_qget_writer_data_lifecycle (wr->m_qos, &autodispose);
}
if (autodispose) {
dds_instance_remove (((dds_writer*) wr)->m_topic, data, DDS_HANDLE_NIL);
action |= DDS_WR_DISPOSE_BIT;
}
ret = dds_write_impl ((dds_writer*)wr, sample, timestamp, action);
dds_entity_unlock(wr);
err:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
dds_return_t
dds_unregister_instance_ih_ts(
_In_ dds_entity_t writer,
_In_opt_ dds_instance_handle_t handle,
_In_ dds_time_t timestamp)
{
dds_return_t ret = DDS_RETCODE_OK;
dds__retcode_t rc;
bool autodispose = true;
dds_write_action action = DDS_WR_ACTION_UNREGISTER;
dds_entity *wr;
struct tkmap *map;
const dds_topic *topic;
void *sample;
DDS_REPORT_STACK();
rc = dds_entity_lock(writer, DDS_KIND_WRITER, &wr);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking writer");
goto err;
}
if (wr->m_qos) {
dds_qget_writer_data_lifecycle (wr->m_qos, &autodispose);
}
if (autodispose) {
dds_instance_remove (((dds_writer*) wr)->m_topic, NULL, handle);
action |= DDS_WR_DISPOSE_BIT;
}
map = gv.m_tkmap;
topic = dds_instance_info((dds_entity*)wr);
sample = dds_alloc (topic->m_descriptor->m_size);
if (dds_tkmap_get_key (map, handle, sample)) {
ret = dds_write_impl ((dds_writer*)wr, sample, timestamp, action);
} else{
ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET, "No instance related with the provided handle is found");
}
dds_sample_free (sample, topic->m_descriptor, DDS_FREE_ALL);
dds_entity_unlock(wr);
err:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
dds_return_t
dds_writedispose_ts(
_In_ dds_entity_t writer,
_In_ const void *data,
_In_ dds_time_t timestamp)
{
dds_return_t ret;
dds__retcode_t rc;
dds_writer *wr;
DDS_REPORT_STACK();
rc = dds_writer_lock(writer, &wr);
if (rc == DDS_RETCODE_OK) {
ret = dds_write_impl (wr, data, timestamp, DDS_WR_ACTION_WRITE_DISPOSE);
if (ret == DDS_RETCODE_OK) {
dds_instance_remove (wr->m_topic, data, DDS_HANDLE_NIL);
}
dds_writer_unlock(wr);
} else {
ret = DDS_ERRNO(rc, "Error occurred on locking writer");
}
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
static dds_return_t
dds_dispose_impl(
_In_ dds_writer *wr,
_In_ const void *data,
_In_ dds_instance_handle_t handle,
_In_ dds_time_t timestamp)
{
dds_return_t ret;
assert(wr);
ret = dds_write_impl(wr, data, timestamp, DDS_WR_ACTION_DISPOSE);
if (ret == DDS_RETCODE_OK) {
dds_instance_remove (wr->m_topic, data, handle);
}
return ret;
}
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
dds_return_t
dds_dispose_ts(
_In_ dds_entity_t writer,
_In_ const void *data,
_In_ dds_time_t timestamp)
{
dds_return_t ret;
dds__retcode_t rc;
dds_writer *wr;
DDS_REPORT_STACK();
rc = dds_writer_lock(writer, &wr);
if (rc == DDS_RETCODE_OK) {
ret = dds_dispose_impl(wr, data, DDS_HANDLE_NIL, timestamp);
dds_writer_unlock(wr);
} else {
ret = DDS_ERRNO(rc, "Error occurred on locking writer");
}
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
dds_return_t
dds_dispose_ih_ts(
_In_ dds_entity_t writer,
_In_ dds_instance_handle_t handle,
_In_ dds_time_t timestamp)
{
dds_return_t ret;
dds__retcode_t rc;
dds_writer *wr;
DDS_REPORT_STACK();
rc = dds_writer_lock(writer, &wr);
if (rc == DDS_RETCODE_OK) {
struct tkmap *map = gv.m_tkmap;
const dds_topic *topic = dds_instance_info((dds_entity*)wr);
void *sample = dds_alloc (topic->m_descriptor->m_size);
if (dds_tkmap_get_key (map, handle, sample)) {
ret = dds_dispose_impl(wr, sample, handle, timestamp);
} else {
ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET, "No instance related with the provided handle is found");
}
dds_free(sample);
dds_writer_unlock(wr);
} else {
ret = DDS_ERRNO(rc, "Error occurred on locking writer");
}
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK)
dds_instance_handle_t
dds_instance_lookup(
dds_entity_t entity,
const void *data)
{
dds_instance_handle_t ih = DDS_HANDLE_NIL;
const dds_topic * topic;
struct tkmap * map = gv.m_tkmap;
serdata_t sd;
dds_return_t ret;
DDS_REPORT_STACK();
if(data == NULL){
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument data is NULL");
goto err;
}
topic = dds_instance_info_by_hdl (entity);
if (topic) {
sd = serialize_key (gv.serpool, topic->m_stopic, data);
ih = dds_tkmap_lookup (map, sd);
ddsi_serdata_unref (sd);
ret = DDS_RETCODE_OK;
} else {
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Acquired topic is NULL");
}
err:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ih;
}
_Pre_satisfies_(entity & DDS_ENTITY_KIND_MASK)
int
dds_instance_get_key(
dds_entity_t entity,
dds_instance_handle_t inst,
void *data)
{
dds_return_t ret;
const dds_topic * topic;
struct tkmap * map = gv.m_tkmap;
DDS_REPORT_STACK();
if(data == NULL){
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument data is NULL");
goto err;
}
topic = dds_instance_info_by_hdl (entity);
if(topic == NULL){
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Could not find topic related to the given entity");
goto err;
}
memset (data, 0, topic->m_descriptor->m_size);
if (dds_tkmap_get_key (map, inst, data)) {
ret = DDS_RETCODE_OK;
} else{
ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET, "No instance related with the provided entity is found");
}
err:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}

166
src/core/ddsc/src/dds_key.c Normal file
View file

@ -0,0 +1,166 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include "dds__key.h"
#include "dds__stream.h"
#include "ddsi/ddsi_ser.h"
#include "ddsi/q_bswap.h"
#include "ddsi/q_md5.h"
void dds_key_md5 (dds_key_hash_t * kh)
{
md5_state_t md5st;
md5_init (&md5st);
md5_append (&md5st, (md5_byte_t*) kh->m_key_buff, kh->m_key_len);
md5_finish (&md5st, (unsigned char *) kh->m_hash);
}
/*
dds_key_gen: Generates key and keyhash for a sample.
See section 9.6.3.3 of DDSI spec.
*/
void dds_key_gen
(
const dds_topic_descriptor_t * const desc,
dds_key_hash_t * kh,
const char * sample
)
{
const char * src;
const uint32_t * op;
uint32_t i;
uint32_t len = 0;
char * dst;
assert (desc->m_nkeys);
assert (kh->m_hash[0] == 0 && kh->m_hash[15] == 0);
kh->m_flags = DDS_KEY_SET | DDS_KEY_HASH_SET;
/* Select key buffer to use */
if (desc->m_flagset & DDS_TOPIC_FIXED_KEY)
{
kh->m_flags |= DDS_KEY_IS_HASH;
kh->m_key_len = sizeof (kh->m_hash);
dst = kh->m_hash;
}
else
{
/* Calculate key length */
for (i = 0; i < desc->m_nkeys; i++)
{
op = desc->m_ops + desc->m_keys[i].m_index;
src = sample + op[1];
switch (DDS_OP_TYPE (*op))
{
case DDS_OP_VAL_1BY: len += 1; break;
case DDS_OP_VAL_2BY: len += 2; break;
case DDS_OP_VAL_4BY: len += 4; break;
case DDS_OP_VAL_8BY: len += 8; break;
case DDS_OP_VAL_STR: src = *((char**) src); /* Fall-through intentional */
case DDS_OP_VAL_BST: len += (uint32_t) (5 + strlen (src)); break;
case DDS_OP_VAL_ARR:
len += op[2] * dds_op_size[DDS_OP_SUBTYPE (*op)];
break;
default: assert (0);
}
}
kh->m_key_len = len;
if (len > kh->m_key_buff_size)
{
kh->m_key_buff = dds_realloc_zero (kh->m_key_buff, len);
kh->m_key_buff_size = len;
}
dst = kh->m_key_buff;
}
/* Write keys to buffer (Big Endian CDR encoded with no padding) */
for (i = 0; i < desc->m_nkeys; i++)
{
op = desc->m_ops + desc->m_keys[i].m_index;
src = sample + op[1];
assert ((*op & DDS_OP_FLAG_KEY) && ((DDS_OP_MASK & *op) == DDS_OP_ADR));
switch (DDS_OP_TYPE (*op))
{
case DDS_OP_VAL_1BY:
{
*dst = *src;
dst++;
break;
}
case DDS_OP_VAL_2BY:
{
uint16_t u16 = toBE2u (*((const uint16_t*) src));
memcpy (dst, &u16, sizeof (u16));
dst += sizeof (u16);
break;
}
case DDS_OP_VAL_4BY:
{
uint32_t u32 = toBE4u (*((const uint32_t*) src));
memcpy (dst, &u32, sizeof (u32));
dst += sizeof (u32);
break;
}
case DDS_OP_VAL_8BY:
{
uint64_t u64 = toBE8u (*((const uint64_t*) src));
memcpy (dst, &u64, sizeof (u64));
dst += sizeof (u64);
break;
}
case DDS_OP_VAL_STR:
{
src = *((char**) src);
} /* Fall-through intentional */
case DDS_OP_VAL_BST:
{
uint32_t u32;
len = (uint32_t) (strlen (src) + 1);
u32 = toBE4u (len);
memcpy (dst, &u32, sizeof (u32));
dst += sizeof (u32);
memcpy (dst, src, len);
dst += len;
break;
}
case DDS_OP_VAL_ARR:
{
uint32_t size = dds_op_size[DDS_OP_SUBTYPE (*op)];
len = size * op[2];
memcpy (dst, src, len);
if (dds_stream_endian () && (size != 1u))
{
dds_stream_swap (dst, size, op[2]);
}
dst += len;
break;
}
default: assert (0);
}
}
/* Hash is md5 of key */
if ((kh->m_flags & DDS_KEY_IS_HASH) == 0)
{
dds_key_md5 (kh);
}
}

View file

@ -0,0 +1,462 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include "ddsc/dds.h"
#include "dds__listener.h"
#include "dds__report.h"
_Ret_notnull_
dds_listener_t*
dds_listener_create(_In_opt_ void* arg)
{
c_listener_t *l = dds_alloc(sizeof(*l));
dds_listener_reset(l);
l->arg = arg;
return l;
}
void
dds_listener_delete(_In_ _Post_invalid_ dds_listener_t * __restrict listener)
{
if (listener) {
dds_free(listener);
}
}
void
dds_listener_reset(_Out_ dds_listener_t * __restrict listener)
{
if (listener) {
c_listener_t *l = listener;
l->on_data_available = DDS_LUNSET;
l->on_data_on_readers = DDS_LUNSET;
l->on_inconsistent_topic = DDS_LUNSET;
l->on_liveliness_changed = DDS_LUNSET;
l->on_liveliness_lost = DDS_LUNSET;
l->on_offered_deadline_missed = DDS_LUNSET;
l->on_offered_incompatible_qos = DDS_LUNSET;
l->on_publication_matched = DDS_LUNSET;
l->on_requested_deadline_missed = DDS_LUNSET;
l->on_requested_incompatible_qos = DDS_LUNSET;
l->on_sample_lost = DDS_LUNSET;
l->on_sample_rejected = DDS_LUNSET;
l->on_subscription_matched = DDS_LUNSET;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
}
}
void
dds_listener_copy(_Out_ dds_listener_t * __restrict dst, _In_ const dds_listener_t * __restrict src)
{
const c_listener_t *srcl = src;
c_listener_t *dstl = dst;
if(!src){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument source(src) is NULL");
return ;
}
if(!dst){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument destination(dst) is NULL");
return ;
}
dstl->on_data_available = srcl->on_data_available;
dstl->on_data_on_readers = srcl->on_data_on_readers;
dstl->on_inconsistent_topic = srcl->on_inconsistent_topic;
dstl->on_liveliness_changed = srcl->on_liveliness_changed;
dstl->on_liveliness_lost = srcl->on_liveliness_lost;
dstl->on_offered_deadline_missed = srcl->on_offered_deadline_missed;
dstl->on_offered_incompatible_qos = srcl->on_offered_incompatible_qos;
dstl->on_publication_matched = srcl->on_publication_matched;
dstl->on_requested_deadline_missed = srcl->on_requested_deadline_missed;
dstl->on_requested_incompatible_qos = srcl->on_requested_incompatible_qos;
dstl->on_sample_lost = srcl->on_sample_lost;
dstl->on_sample_rejected = srcl->on_sample_rejected;
dstl->on_subscription_matched = srcl->on_subscription_matched;
}
void
dds_listener_merge (_Inout_ dds_listener_t * __restrict dst, _In_ const dds_listener_t * __restrict src)
{
const c_listener_t *srcl = src;
c_listener_t *dstl = dst;
if(!src){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument source(src) is NULL");
return ;
}
if(!dst){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument destination(dst) is NULL");
return ;
}
if (dstl->on_data_available == DDS_LUNSET) {
dstl->on_data_available = srcl->on_data_available;
}
if (dstl->on_data_on_readers == DDS_LUNSET) {
dstl->on_data_on_readers = srcl->on_data_on_readers;
}
if (dstl->on_inconsistent_topic == DDS_LUNSET) {
dstl->on_inconsistent_topic = srcl->on_inconsistent_topic;
}
if (dstl->on_liveliness_changed == DDS_LUNSET) {
dstl->on_liveliness_changed = srcl->on_liveliness_changed;
}
if (dstl->on_liveliness_lost == DDS_LUNSET) {
dstl->on_liveliness_lost = srcl->on_liveliness_lost;
}
if (dstl->on_offered_deadline_missed == DDS_LUNSET) {
dstl->on_offered_deadline_missed = srcl->on_offered_deadline_missed;
}
if (dstl->on_offered_incompatible_qos == DDS_LUNSET) {
dstl->on_offered_incompatible_qos = srcl->on_offered_incompatible_qos;
}
if (dstl->on_publication_matched == DDS_LUNSET) {
dstl->on_publication_matched = srcl->on_publication_matched;
}
if (dstl->on_requested_deadline_missed == DDS_LUNSET) {
dstl->on_requested_deadline_missed = srcl->on_requested_deadline_missed;
}
if (dstl->on_requested_incompatible_qos == DDS_LUNSET) {
dstl->on_requested_incompatible_qos = srcl->on_requested_incompatible_qos;
}
if (dstl->on_sample_lost == DDS_LUNSET) {
dstl->on_sample_lost = srcl->on_sample_lost;
}
if (dstl->on_sample_rejected == DDS_LUNSET) {
dstl->on_sample_rejected = srcl->on_sample_rejected;
}
if (dstl->on_subscription_matched == DDS_LUNSET) {
dstl->on_subscription_matched = srcl->on_subscription_matched;
}
}
/************************************************************************************************
* Setters
************************************************************************************************/
void
dds_lset_data_available (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_data_available_fn callback)
{
if (listener) {
((c_listener_t*)listener)->on_data_available = callback;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
}
}
void
dds_lset_data_on_readers (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_data_on_readers_fn callback)
{
if (listener) {
((c_listener_t*)listener)->on_data_on_readers = callback;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
}
}
void
dds_lset_inconsistent_topic (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_inconsistent_topic_fn callback)
{
if (listener) {
((c_listener_t*)listener)->on_inconsistent_topic = callback;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
}
}
void
dds_lset_liveliness_changed (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_liveliness_changed_fn callback)
{
if (listener) {
((c_listener_t*)listener)->on_liveliness_changed = callback;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
}
}
void
dds_lset_liveliness_lost (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_liveliness_lost_fn callback)
{
if (listener) {
((c_listener_t*)listener)->on_liveliness_lost = callback;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
}
}
void
dds_lset_offered_deadline_missed (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_offered_deadline_missed_fn callback)
{
if (listener) {
((c_listener_t*)listener)->on_offered_deadline_missed = callback;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
}
}
void
dds_lset_offered_incompatible_qos (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_offered_incompatible_qos_fn callback)
{
if (listener) {
((c_listener_t*)listener)->on_offered_incompatible_qos = callback;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
}
}
void
dds_lset_publication_matched (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_publication_matched_fn callback)
{
if (listener) {
((c_listener_t*)listener)->on_publication_matched = callback;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
}
}
void
dds_lset_requested_deadline_missed (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_requested_deadline_missed_fn callback)
{
if (listener) {
((c_listener_t*)listener)->on_requested_deadline_missed = callback;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
}
}
void
dds_lset_requested_incompatible_qos (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_requested_incompatible_qos_fn callback)
{
if (listener) {
((c_listener_t*)listener)->on_requested_incompatible_qos = callback;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
}
}
void
dds_lset_sample_lost (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_sample_lost_fn callback)
{
if (listener) {
((c_listener_t*)listener)->on_sample_lost = callback;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
}
}
void
dds_lset_sample_rejected (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_sample_rejected_fn callback)
{
if (listener) {
((c_listener_t*)listener)->on_sample_rejected = callback;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
}
}
void
dds_lset_subscription_matched (_Inout_ dds_listener_t * __restrict listener, _In_opt_ dds_on_subscription_matched_fn callback)
{
if (listener) {
((c_listener_t*)listener)->on_subscription_matched = callback;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
}
}
/************************************************************************************************
* Getters
************************************************************************************************/
void
dds_lget_data_available (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_data_available_fn *callback)
{
if(!callback){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument callback is NULL");
return ;
}
if (!listener) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
return ;
}
*callback = ((c_listener_t*)listener)->on_data_available;
}
void
dds_lget_data_on_readers (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_data_on_readers_fn *callback)
{
if(!callback){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument callback is NULL");
return ;
}
if (!listener) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
return ;
}
*callback = ((c_listener_t*)listener)->on_data_on_readers;
}
void dds_lget_inconsistent_topic (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_inconsistent_topic_fn *callback)
{
if(!callback){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument callback is NULL");
return ;
}
if (!listener) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
return ;
}
*callback = ((c_listener_t*)listener)->on_inconsistent_topic;
}
void
dds_lget_liveliness_changed (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_liveliness_changed_fn *callback)
{
if(!callback){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument callback is NULL");
return ;
}
if (!listener) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
return ;
}
*callback = ((c_listener_t*)listener)->on_liveliness_changed;
}
void
dds_lget_liveliness_lost (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_liveliness_lost_fn *callback)
{
if(!callback){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument callback is NULL");
return ;
}
if (!listener) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
return ;
}
*callback = ((c_listener_t*)listener)->on_liveliness_lost;
}
void
dds_lget_offered_deadline_missed (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_offered_deadline_missed_fn *callback)
{
if(!callback){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument callback is NULL");
return ;
}
if (!listener) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
return ;
}
*callback = ((c_listener_t*)listener)->on_offered_deadline_missed;
}
void
dds_lget_offered_incompatible_qos (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_offered_incompatible_qos_fn *callback)
{
if(!callback){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument callback is NULL");
return ;
}
if (!listener) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
return ;
}
*callback = ((c_listener_t*)listener)->on_offered_incompatible_qos;
}
void
dds_lget_publication_matched (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_publication_matched_fn *callback)
{
if(!callback){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument callback is NULL");
return ;
}
if (!listener) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
return ;
}
*callback = ((c_listener_t*)listener)->on_publication_matched;
}
void
dds_lget_requested_deadline_missed (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_requested_deadline_missed_fn *callback)
{
if(!callback) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument callback is NULL");
return ;
}
if (!listener) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
return ;
}
*callback = ((c_listener_t*)listener)->on_requested_deadline_missed;
}
void
dds_lget_requested_incompatible_qos (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_requested_incompatible_qos_fn *callback)
{
if(!callback) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument callback is NULL");
return ;
}
if (!listener) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
return ;
}
*callback = ((c_listener_t*)listener)->on_requested_incompatible_qos;
}
void
dds_lget_sample_lost (_In_ const dds_listener_t *__restrict listener, _Outptr_result_maybenull_ dds_on_sample_lost_fn *callback)
{
if(!callback) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument callback is NULL");
return ;
}
if (!listener) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
return ;
}
*callback = ((c_listener_t*)listener)->on_sample_lost;
}
void
dds_lget_sample_rejected (_In_ const dds_listener_t *__restrict listener, _Outptr_result_maybenull_ dds_on_sample_rejected_fn *callback)
{
if(!callback) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument callback is NULL");
return ;
}
if (!listener) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
return ;
}
*callback = ((c_listener_t*)listener)->on_sample_rejected;
}
void
dds_lget_subscription_matched (_In_ const dds_listener_t * __restrict listener, _Outptr_result_maybenull_ dds_on_subscription_matched_fn *callback)
{
if(!callback) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument callback is NULL");
return ;
}
if (!listener) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument listener is NULL");
return ;
}
*callback = ((c_listener_t*)listener)->on_subscription_matched;
}

View file

@ -0,0 +1,73 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include <stdarg.h>
#include "ddsc/dds.h"
#include "ddsi/q_log.h"
#define DDS_FMT_MAX 128
void dds_log_info (const char * fmt, ...)
{
va_list args;
va_start (args, fmt);
nn_vlog (LC_INFO, fmt, args);
va_end (args);
}
void dds_log_warn (const char * fmt, ...)
{
va_list args;
char fmt2 [DDS_FMT_MAX];
strcpy (fmt2, "<Warning> ");
strncat (fmt2, fmt, DDS_FMT_MAX - 11);
fmt2[DDS_FMT_MAX-1] = 0;
fmt = fmt2;
va_start (args, fmt);
nn_vlog (LC_WARNING, fmt, args);
va_end (args);
}
void dds_log_error (const char * fmt, ...)
{
va_list args;
char fmt2 [DDS_FMT_MAX];
strcpy (fmt2, "<Error> ");
strncat (fmt2, fmt, DDS_FMT_MAX - 9);
fmt2[DDS_FMT_MAX-1] = 0;
fmt = fmt2;
va_start (args, fmt);
nn_vlog (LC_ERROR, fmt, args);
va_end (args);
}
void dds_log_fatal (const char * fmt, ...)
{
va_list args;
char fmt2 [DDS_FMT_MAX];
strcpy (fmt2, "<Fatal> ");
strncat (fmt2, fmt, DDS_FMT_MAX - 9);
fmt2[DDS_FMT_MAX-1] = 0;
fmt = fmt2;
va_start (args, fmt);
nn_vlog (LC_FATAL, fmt, args);
va_end (args);
DDS_FAIL (fmt);
}

View file

@ -0,0 +1,289 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include "ddsi/q_entity.h"
#include "ddsi/q_thread.h"
#include "ddsi/q_config.h"
#include "q__osplser.h"
#include "dds__init.h"
#include "dds__qos.h"
#include "dds__domain.h"
#include "dds__participant.h"
#include "dds__err.h"
#include "dds__report.h"
#define DDS_PARTICIPANT_STATUS_MASK 0
/* List of created participants */
static dds_entity * dds_pp_head = NULL;
static dds_return_t
dds_participant_status_validate(
uint32_t mask)
{
return (mask & ~(DDS_PARTICIPANT_STATUS_MASK)) ?
DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument mask is invalid") :
DDS_RETCODE_OK;
}
static dds_return_t
dds_participant_delete(
dds_entity *e)
{
struct thread_state1 * const thr = lookup_thread_state ();
const bool asleep = !vtime_awake_p (thr->vtime);
dds_entity *prev = NULL;
dds_entity *iter;
assert(e);
assert(thr);
assert(dds_entity_kind(e->m_hdl) == DDS_KIND_PARTICIPANT);
if (asleep) {
thread_state_awake(thr);
}
dds_domain_free (e->m_domain);
os_mutexLock (&dds_global.m_mutex);
iter = dds_pp_head;
while (iter) {
if (iter == e) {
if (prev) {
prev->m_next = iter->m_next;
} else {
dds_pp_head = iter->m_next;
}
break;
}
prev = iter;
iter = iter->m_next;
}
os_mutexUnlock (&dds_global.m_mutex);
assert (iter);
if (asleep) {
thread_state_asleep(thr);
}
/* Every dds_init needs a dds_fini. */
dds_fini();
return DDS_RETCODE_OK;
}
static dds_return_t
dds_participant_instance_hdl(
dds_entity *e,
dds_instance_handle_t *i)
{
assert(e);
assert(i);
*i = (dds_instance_handle_t)participant_instance_id(&e->m_guid);
return DDS_RETCODE_OK;
}
static dds_return_t
dds_participant_qos_validate(
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = DDS_RETCODE_OK;
assert(qos);
/* Check consistency. */
if ((qos->present & QP_USER_DATA) && !validate_octetseq(&qos->user_data)) {
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "User data QoS policy is inconsistent and caused an error");
}
if ((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy(&qos->entity_factory)) {
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Prismtech entity factory QoS policy is inconsistent and caused an error");
}
return ret;
}
static dds_return_t
dds_participant_qos_set(
dds_entity *e,
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = dds_participant_qos_validate(qos, enabled);
if (ret == DDS_RETCODE_OK) {
if (enabled) {
/* TODO: CHAM-95: DDSI does not support changing QoS policies. */
ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED, "Changing the participant QoS is not supported.");
}
}
return ret;
}
_Must_inspect_result_ dds_entity_t
dds_create_participant(
_In_ const dds_domainid_t domain,
_In_opt_ const dds_qos_t *qos,
_In_opt_ const dds_listener_t *listener)
{
int q_rc;
dds_return_t ret;
dds_entity_t e;
nn_guid_t guid;
dds_participant * pp;
nn_plist_t plist;
dds_qos_t * new_qos = NULL;
struct thread_state1 * thr;
bool asleep;
/* Be sure the DDS lifecycle resources are initialized. */
dds__startup();
/* Make sure DDS instance is initialized. */
ret = dds_init();
if (ret != DDS_RETCODE_OK) {
e = (dds_entity_t)ret;
goto fail_dds_init;
}
/* Report stack is only useful after dds (and thus os) init. */
DDS_REPORT_STACK();
/* Check domain id */
ret = dds__check_domain (domain);
if (ret != DDS_RETCODE_OK) {
e = (dds_entity_t)ret;
goto fail_domain_check;
}
/* Validate qos */
if (qos) {
ret = dds_participant_qos_validate (qos, false);
if (ret != DDS_RETCODE_OK) {
e = (dds_entity_t)ret;
goto fail_qos_validation;
}
new_qos = dds_qos_create ();
/* Only returns failure when one of the qos args is NULL, which
* is not the case here. */
(void)dds_qos_copy(new_qos, qos);
} else {
/* Use default qos. */
new_qos = dds_qos_create ();
}
/* Translate qos */
nn_plist_init_empty(&plist);
dds_qos_merge (&plist.qos, new_qos);
thr = lookup_thread_state ();
asleep = !vtime_awake_p (thr->vtime);
if (asleep) {
thread_state_awake (thr);
}
q_rc = new_participant (&guid, 0, &plist);
if (asleep) {
thread_state_asleep (thr);
}
nn_plist_fini (&plist);
if (q_rc != 0) {
e = DDS_ERRNO(DDS_RETCODE_ERROR, "Internal error");
goto fail_new_participant;
}
pp = dds_alloc (sizeof (*pp));
e = dds_entity_init (&pp->m_entity, NULL, DDS_KIND_PARTICIPANT, new_qos, listener, DDS_PARTICIPANT_STATUS_MASK);
if (e < 0) {
goto fail_entity_init;
}
pp->m_entity.m_guid = guid;
pp->m_entity.m_domain = dds_domain_create (dds_domain_default());
pp->m_entity.m_domainid = dds_domain_default();
pp->m_entity.m_deriver.delete = dds_participant_delete;
pp->m_entity.m_deriver.set_qos = dds_participant_qos_set;
pp->m_entity.m_deriver.get_instance_hdl = dds_participant_instance_hdl;
pp->m_entity.m_deriver.validate_status = dds_participant_status_validate;
pp->m_builtin_subscriber = 0;
/* Add participant to extent */
os_mutexLock (&dds_global.m_mutex);
pp->m_entity.m_next = dds_pp_head;
dds_pp_head = &pp->m_entity;
os_mutexUnlock (&dds_global.m_mutex);
DDS_REPORT_FLUSH(false);
return e;
fail_entity_init:
dds_free(pp);
fail_new_participant:
dds_qos_delete(new_qos);
fail_qos_validation:
fail_domain_check:
DDS_REPORT_FLUSH(true);
dds_fini();
fail_dds_init:
return e;
}
_Check_return_ dds_return_t
dds_lookup_participant(
_In_ dds_domainid_t domain_id,
_Out_opt_ dds_entity_t *participants,
_In_ size_t size)
{
dds_return_t ret = 0;
/* Be sure the DDS lifecycle resources are initialized. */
dds__startup();
DDS_REPORT_STACK();
if ((participants != NULL) && ((size <= 0) || (size >= INT32_MAX))) {
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Array is given, but with invalid size");
goto err;
}
if ((participants == NULL) && (size != 0)) {
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Size is given, but no array");
goto err;
}
if(participants){
participants[0] = 0;
}
os_mutexLock (&dds__init_mutex);
/* Check if dds is intialized. */
if (dds_global.m_init_count > 0) {
dds_entity* iter;
os_mutexLock (&dds_global.m_mutex);
iter = dds_pp_head;
while (iter) {
if(iter->m_domainid == domain_id) {
if((size_t)ret < size) {
participants[ret] = iter->m_hdl;
}
ret++;
}
iter = iter->m_next;
}
os_mutexUnlock (&dds_global.m_mutex);
}
os_mutexUnlock (&dds__init_mutex);
err:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}

View file

@ -0,0 +1,220 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include "dds__listener.h"
#include "dds__qos.h"
#include "dds__err.h"
#include "ddsi/q_entity.h"
#include "dds__report.h"
#include "ddsc/ddsc_project.h"
#define DDS_PUBLISHER_STATUS_MASK 0
static dds_return_t
dds_publisher_instance_hdl(
dds_entity *e,
dds_instance_handle_t *i)
{
assert(e);
assert(i);
/* TODO: Get/generate proper handle. */
return DDS_ERRNO(DDS_RETCODE_UNSUPPORTED, "Getting publisher instance handle is not supported");
}
static dds_return_t
dds_publisher_qos_validate(
_In_ const dds_qos_t *qos,
_In_ bool enabled)
{
dds_return_t ret = DDS_RETCODE_OK;
assert(qos);
/* Check consistency. */
if((qos->present & QP_GROUP_DATA) && !validate_octetseq(&qos->group_data)){
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Group data policy is inconsistent and caused an error");
}
if((qos->present & QP_PRESENTATION) && (validate_presentation_qospolicy(&qos->presentation) != 0)){
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Presentation policy is inconsistent and caused an error");
}
if((qos->present & QP_PARTITION) && !validate_stringseq(&qos->partition)){
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Partition policy is inconsistent and caused an error");
}
if((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy(&qos->entity_factory)){
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Prismtech entity factory policy is inconsistent and caused an error");
}
if(ret == DDS_RETCODE_OK && enabled && (qos->present & QP_PRESENTATION)){
/* TODO: Improve/check immutable check. */
ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY, "Presentation policy is immutable");
}
return ret;
}
static dds_return_t
dds_publisher_qos_set(
dds_entity *e,
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = dds_publisher_qos_validate(qos, enabled);
if (ret == DDS_RETCODE_OK) {
if (enabled) {
/* TODO: CHAM-95: DDSI does not support changing QoS policies. */
ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED, DDSC_PROJECT_NAME" does not support changing QoS policies yet");
}
}
return ret;
}
static dds_return_t dds_publisher_status_validate (uint32_t mask)
{
return (mask & ~(DDS_PUBLISHER_STATUS_MASK)) ?
DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Invalid status mask") :
DDS_RETCODE_OK;
}
_Pre_satisfies_((participant & DDS_ENTITY_KIND_MASK) == DDS_KIND_PARTICIPANT)
_Must_inspect_result_ dds_entity_t
dds_create_publisher(
_In_ dds_entity_t participant,
_In_opt_ const dds_qos_t *qos,
_In_opt_ const dds_listener_t *listener)
{
dds_entity * par;
dds_publisher * pub;
dds_entity_t hdl;
dds_qos_t * new_qos = NULL;
dds_return_t ret;
dds__retcode_t rc;
DDS_REPORT_STACK();
rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par);
if (rc != DDS_RETCODE_OK) {
hdl = DDS_ERRNO(rc, "Error occurred on locking participant");
goto lock_err;
}
/* Validate qos */
if (qos) {
ret = dds_publisher_qos_validate(qos, false);
if (ret != DDS_RETCODE_OK) {
hdl = ret;
goto qos_err;
}
new_qos = dds_qos_create ();
/* Only returns failure when one of the qos args is NULL, which
* is not the case here. */
(void)dds_qos_copy(new_qos, qos);
}
/* Create publisher */
pub = dds_alloc (sizeof (*pub));
hdl = dds_entity_init (&pub->m_entity, par, DDS_KIND_PUBLISHER, new_qos, listener, DDS_PUBLISHER_STATUS_MASK);
pub->m_entity.m_deriver.set_qos = dds_publisher_qos_set;
pub->m_entity.m_deriver.get_instance_hdl = dds_publisher_instance_hdl;
pub->m_entity.m_deriver.validate_status = dds_publisher_status_validate;
qos_err:
dds_entity_unlock(par);
lock_err:
DDS_REPORT_FLUSH(hdl <= 0);
return hdl;
}
_Pre_satisfies_((publisher & DDS_ENTITY_KIND_MASK) == DDS_KIND_PUBLISHER)
DDS_EXPORT dds_return_t
dds_suspend(
_In_ dds_entity_t publisher)
{
dds_return_t ret;
DDS_REPORT_STACK();
if(dds_entity_kind(publisher) != DDS_KIND_PUBLISHER) {
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Provided entity is not a publisher kind");
goto err;
}
/* TODO: CHAM-123 Currently unsupported. */
ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED, "Suspend publication operation does not being supported yet");
err:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_((publisher & DDS_ENTITY_KIND_MASK) == DDS_KIND_PUBLISHER)
dds_return_t
dds_resume(
_In_ dds_entity_t publisher)
{
dds_return_t ret = DDS_RETCODE_OK;
DDS_REPORT_STACK();
if(dds_entity_kind(publisher) != DDS_KIND_PUBLISHER) {
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER,"Provided entity is not a publisher kind");
goto err;
}
/* TODO: CHAM-123 Currently unsupported. */
ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED, "Suspend publication operation does not being supported yet");
err:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_(((publisher_or_writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER ) ||\
((publisher_or_writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_PUBLISHER) )
dds_return_t
dds_wait_for_acks(
_In_ dds_entity_t publisher_or_writer,
_In_ dds_duration_t timeout)
{
dds_return_t ret;
DDS_REPORT_STACK();
/* TODO: CHAM-125 Currently unsupported. */
OS_UNUSED_ARG(timeout);
switch(dds_entity_kind(publisher_or_writer)) {
case DDS_KIND_WRITER:
ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED, "Wait for acknowledgments on a writer is not being supported yet");
break;
case DDS_KIND_PUBLISHER:
ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED, "Wait for acknowledgments on a publisher is not being supported yet");
break;
default:
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Provided entity is not a publisher nor a writer");
break;
}
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
dds_return_t
dds_publisher_begin_coherent(
_In_ dds_entity_t e)
{
/* TODO: CHAM-124 Currently unsupported. */
return DDS_ERRNO(DDS_RETCODE_UNSUPPORTED, "Using coherency to get a coherent data set is not being supported yet");
}
dds_return_t
dds_publisher_end_coherent(
_In_ dds_entity_t e)
{
/* TODO: CHAM-124 Currently unsupported. */
return DDS_ERRNO(DDS_RETCODE_UNSUPPORTED, "Using coherency to get a coherent data set is not being supported yet");
}

996
src/core/ddsc/src/dds_qos.c Normal file
View file

@ -0,0 +1,996 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include "dds__qos.h"
#include "dds__err.h"
#include "ddsi/q_config.h"
#include "dds__report.h"
/* TODO: dd_duration_t is converted to nn_ddsi_time_t declared in q_time.h
This structure contain seconds and fractions.
Revisit on the conversion as default values are { 0x7fffffff, 0xffffffff }
*/
static void
dds_qos_data_copy_in(
_Inout_ nn_octetseq_t * data,
_In_reads_bytes_opt_(sz) const void * __restrict value,
_In_ size_t sz)
{
if (data->value) {
dds_free (data->value);
data->value = NULL;
}
data->length = (uint32_t) sz;
if (sz && value) {
data->value = dds_alloc (sz);
memcpy (data->value, value, sz);
}
}
static void
dds_qos_data_copy_out(
_In_ const nn_octetseq_t * data,
_When_(*sz == 0, _At_(*value, _Post_null_))
_When_(*sz > 0, _At_(*value, _Post_notnull_))
_Outptr_result_bytebuffer_all_maybenull_(*sz) void ** value,
_Out_ size_t * sz)
{
if ((*sz = data->length) != 0) {
assert(data->value);
*value = dds_alloc(data->length);
memcpy(*value, data->value, data->length);
} else {
*value = NULL;
}
}
bool
validate_octetseq(
const nn_octetseq_t* seq)
{
/* default value is NULL with length 0 */
return (((seq->length == 0) && (seq->value == NULL)) || (seq->length > 0));
}
bool
validate_stringseq(
const nn_stringseq_t* seq)
{
if (seq->n != 0) {
unsigned i;
for (i = 0; i < seq->n; i++) {
if (!seq->strs[i]) {
break;
}
}
return (seq->n == i);
} else {
return (seq->strs == NULL);
}
}
bool
validate_entityfactory_qospolicy(
const nn_entity_factory_qospolicy_t * entityfactory)
{
/* Bools must be 0 or 1, i.e., only the lsb may be set */
return !(entityfactory->autoenable_created_entities & ~1);
}
bool
validate_reliability_qospolicy(
const nn_reliability_qospolicy_t * reliability)
{
return (
(reliability->kind == NN_BEST_EFFORT_RELIABILITY_QOS || reliability->kind == NN_RELIABLE_RELIABILITY_QOS) &&
(validate_duration(&reliability->max_blocking_time) == 0)
);
}
bool
validate_deadline_and_timebased_filter(
const nn_duration_t deadline,
const nn_duration_t minimum_separation)
{
return (
(validate_duration(&deadline) == 0) &&
(validate_duration(&minimum_separation) == 0) &&
(nn_from_ddsi_duration(minimum_separation) <= nn_from_ddsi_duration(deadline))
);
}
bool
dds_qos_validate_common (
const dds_qos_t *qos)
{
return !(
((qos->present & QP_DURABILITY) && (validate_durability_qospolicy (&qos->durability) != 0)) ||
((qos->present & QP_DEADLINE) && (validate_duration (&qos->deadline.deadline) != 0)) ||
((qos->present & QP_LATENCY_BUDGET) && (validate_duration (&qos->latency_budget.duration) != 0)) ||
((qos->present & QP_OWNERSHIP) && (validate_ownership_qospolicy (&qos->ownership) != 0)) ||
((qos->present & QP_LIVELINESS) && (validate_liveliness_qospolicy (&qos->liveliness) != 0)) ||
((qos->present & QP_RELIABILITY) && ! validate_reliability_qospolicy (&qos->reliability)) ||
((qos->present & QP_DESTINATION_ORDER) && (validate_destination_order_qospolicy (&qos->destination_order) != 0)) ||
((qos->present & QP_HISTORY) && (validate_history_qospolicy (&qos->history) != 0)) ||
((qos->present & QP_RESOURCE_LIMITS) && (validate_resource_limits_qospolicy (&qos->resource_limits) != 0))
);
}
dds_return_t
dds_qos_validate_mutable_common (
_In_ const dds_qos_t *qos)
{
dds_return_t ret = DDS_RETCODE_OK;
/* TODO: Check whether immutable QoS are changed should actually incorporate change to current QoS */
if (qos->present & QP_DEADLINE) {
ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY, "Deadline QoS policy caused immutable error");
}
if (qos->present & QP_OWNERSHIP) {
ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY, "Ownership QoS policy caused immutable error");
}
if (qos->present & QP_LIVELINESS) {
ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY, "Liveliness QoS policy caused immutable error");
}
if (qos->present & QP_RELIABILITY) {
ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY, "Reliability QoS policy caused immutable error");
}
if (qos->present & QP_DESTINATION_ORDER) {
ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY, "Destination order QoS policy caused immutable error");
}
if (qos->present & QP_HISTORY) {
ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY, "History QoS policy caused immutable error");
}
if (qos->present & QP_RESOURCE_LIMITS) {
ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY, "Resource limits QoS policy caused immutable error");
}
return ret;
}
static void
dds_qos_init_defaults (
_Inout_ dds_qos_t * __restrict qos)
{
assert (qos);
memset (qos, 0, sizeof (*qos));
qos->durability.kind = (nn_durability_kind_t) DDS_DURABILITY_VOLATILE;
qos->deadline.deadline = nn_to_ddsi_duration (DDS_INFINITY);
qos->durability_service.service_cleanup_delay = nn_to_ddsi_duration (0);
qos->durability_service.history.kind = (nn_history_kind_t) DDS_HISTORY_KEEP_LAST;
qos->durability_service.history.depth = 1;
qos->durability_service.resource_limits.max_samples = DDS_LENGTH_UNLIMITED;
qos->durability_service.resource_limits.max_instances = DDS_LENGTH_UNLIMITED;
qos->durability_service.resource_limits.max_samples_per_instance = DDS_LENGTH_UNLIMITED;
qos->presentation.access_scope = (nn_presentation_access_scope_kind_t) DDS_PRESENTATION_INSTANCE;
qos->latency_budget.duration = nn_to_ddsi_duration (0);
qos->ownership.kind = (nn_ownership_kind_t) DDS_OWNERSHIP_SHARED;
qos->liveliness.kind = (nn_liveliness_kind_t) DDS_LIVELINESS_AUTOMATIC;
qos->liveliness.lease_duration = nn_to_ddsi_duration (DDS_INFINITY);
qos->time_based_filter.minimum_separation = nn_to_ddsi_duration (0);
qos->reliability.kind = (nn_reliability_kind_t) DDS_RELIABILITY_BEST_EFFORT;
qos->reliability.max_blocking_time = nn_to_ddsi_duration (DDS_MSECS (100));
qos->lifespan.duration = nn_to_ddsi_duration (DDS_INFINITY);
qos->destination_order.kind = (nn_destination_order_kind_t) DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP;
qos->history.kind = (nn_history_kind_t) DDS_HISTORY_KEEP_LAST;
qos->history.depth = 1;
qos->resource_limits.max_samples = DDS_LENGTH_UNLIMITED;
qos->resource_limits.max_instances = DDS_LENGTH_UNLIMITED;
qos->resource_limits.max_samples_per_instance = DDS_LENGTH_UNLIMITED;
qos->writer_data_lifecycle.autodispose_unregistered_instances = true;
qos->reader_data_lifecycle.autopurge_nowriter_samples_delay = nn_to_ddsi_duration (DDS_INFINITY);
qos->reader_data_lifecycle.autopurge_disposed_samples_delay = nn_to_ddsi_duration (DDS_INFINITY);
}
_Ret_notnull_
dds_qos_t * dds_qos_create (void)
{
dds_qos_t *qos = dds_alloc (sizeof (dds_qos_t));
dds_qos_init_defaults (qos);
return qos;
}
void
dds_qos_reset(
_Out_ dds_qos_t * __restrict qos)
{
if (qos) {
nn_xqos_fini (qos);
dds_qos_init_defaults (qos);
} else {
DDS_WARNING(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void
dds_qos_delete(
_In_ _Post_invalid_ dds_qos_t * __restrict qos)
{
if (qos) {
dds_qos_reset(qos);
dds_free(qos);
}
}
dds_return_t
dds_qos_copy (
_Out_ dds_qos_t * __restrict dst,
_In_ const dds_qos_t * __restrict src)
{
if(!src){
return DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument source(src) is NULL");
}
if(!dst){
return DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument destination(dst) is NULL");
}
nn_xqos_copy (dst, src);
return DDS_RETCODE_OK;
}
void dds_qos_merge (
_Inout_ dds_qos_t * __restrict dst,
_In_ const dds_qos_t * __restrict src)
{
if(!src){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument source(src) is NULL");
return ;
}
if(!dst){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument destination(dst) is NULL");
return ;
}
/* Copy qos from source to destination unless already set */
nn_xqos_mergein_missing (dst, src);
}
void dds_qset_userdata(
_Inout_ dds_qos_t * __restrict qos,
_In_reads_bytes_opt_(sz) const void * __restrict value,
_In_ size_t sz)
{
if (!qos) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
return ;
}
dds_qos_data_copy_in(&qos->user_data, value, sz);
qos->present |= QP_USER_DATA;
}
void dds_qset_topicdata(
_Inout_ dds_qos_t * __restrict qos,
_In_reads_bytes_opt_(sz) const void * __restrict value,
_In_ size_t sz)
{
if (!qos) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
return ;
}
dds_qos_data_copy_in (&qos->topic_data, value, sz);
qos->present |= QP_TOPIC_DATA;
}
void dds_qset_groupdata(
_Inout_ dds_qos_t * __restrict qos,
_In_reads_bytes_opt_(sz) const void * __restrict value,
_In_ size_t sz)
{
if (!qos) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
return ;
}
dds_qos_data_copy_in (&qos->group_data, value, sz);
qos->present |= QP_GROUP_DATA;
}
void dds_qset_durability
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(DDS_DURABILITY_VOLATILE, DDS_DURABILITY_PERSISTENT) dds_durability_kind_t kind
)
{
if (qos) {
qos->durability.kind = (nn_durability_kind_t) kind;
qos->present |= QP_DURABILITY;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void dds_qset_history
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(DDS_HISTORY_KEEP_LAST, DDS_HISTORY_KEEP_ALL) dds_history_kind_t kind,
_In_range_(>=, DDS_LENGTH_UNLIMITED) int32_t depth
)
{
if (qos) {
qos->history.kind = (nn_history_kind_t) kind;
qos->history.depth = depth;
qos->present |= QP_HISTORY;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void dds_qset_resource_limits
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(>=, DDS_LENGTH_UNLIMITED) int32_t max_samples,
_In_range_(>=, DDS_LENGTH_UNLIMITED) int32_t max_instances,
_In_range_(>=, DDS_LENGTH_UNLIMITED) int32_t max_samples_per_instance
)
{
if (qos) {
qos->resource_limits.max_samples = max_samples;
qos->resource_limits.max_instances = max_instances;
qos->resource_limits.max_samples_per_instance = max_samples_per_instance;
qos->present |= QP_RESOURCE_LIMITS;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void dds_qset_presentation
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(DDS_PRESENTATION_INSTANCE, DDS_PRESENTATION_GROUP) dds_presentation_access_scope_kind_t access_scope,
_In_ bool coherent_access,
_In_ bool ordered_access
)
{
if (qos) {
qos->presentation.access_scope = (nn_presentation_access_scope_kind_t) access_scope;
qos->presentation.coherent_access = coherent_access;
qos->presentation.ordered_access = ordered_access;
qos->present |= QP_PRESENTATION;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void dds_qset_lifespan
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(0, DDS_INFINITY) dds_duration_t lifespan
)
{
if (qos) {
qos->lifespan.duration = nn_to_ddsi_duration (lifespan);
qos->present |= QP_LIFESPAN;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void dds_qset_deadline
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(0, DDS_INFINITY) dds_duration_t deadline
)
{
if (qos) {
qos->deadline.deadline = nn_to_ddsi_duration (deadline);
qos->present |= QP_DEADLINE;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void dds_qset_latency_budget
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(0, DDS_INFINITY) dds_duration_t duration
)
{
if (qos) {
qos->latency_budget.duration = nn_to_ddsi_duration (duration);
qos->present |= QP_LATENCY_BUDGET;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void dds_qset_ownership
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(DDS_OWNERSHIP_SHARED, DDS_OWNERSHIP_EXCLUSIVE) dds_ownership_kind_t kind
)
{
if (qos) {
qos->ownership.kind = (nn_ownership_kind_t) kind;
qos->present |= QP_OWNERSHIP;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void dds_qset_ownership_strength
(
_Inout_ dds_qos_t * __restrict qos,
_In_ int32_t value
)
{
if (qos) {
qos->ownership_strength.value = value;
qos->present |= QP_OWNERSHIP_STRENGTH;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void dds_qset_liveliness
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(DDS_LIVELINESS_AUTOMATIC, DDS_LIVELINESS_MANUAL_BY_TOPIC) dds_liveliness_kind_t kind,
_In_range_(0, DDS_INFINITY) dds_duration_t lease_duration
)
{
if (qos) {
qos->liveliness.kind = (nn_liveliness_kind_t) kind;
qos->liveliness.lease_duration = nn_to_ddsi_duration (lease_duration);
qos->present |= QP_LIVELINESS;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void dds_qset_time_based_filter
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(0, DDS_INFINITY) dds_duration_t minimum_separation
)
{
if (qos) {
qos->time_based_filter.minimum_separation = nn_to_ddsi_duration (minimum_separation);
qos->present |= QP_TIME_BASED_FILTER;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void dds_qset_partition
(
_Inout_ dds_qos_t * __restrict qos,
_In_ uint32_t n,
_In_count_(n) _Deref_pre_z_ const char ** __restrict ps
)
{
uint32_t i;
size_t len;
if(!qos) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos may not be NULL");
return ;
}
if(n && !ps) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument ps is NULL, but n (%u) > 0", n);
return ;
}
if (qos->partition.strs != NULL){
for (i = 0; i < qos->partition.n; i++) {
dds_free(qos->partition.strs[i]);
}
dds_free(qos->partition.strs);
qos->partition.strs = NULL;
}
qos->partition.n = n;
if(n){
qos->partition.strs = dds_alloc (sizeof (char*) * n);
}
for (i = 0; i < n; i++) {
len = strlen (ps[i]) + 1;
qos->partition.strs[i] = dds_alloc (len);
strncpy (qos->partition.strs[i], ps[i], len);
}
qos->present |= QP_PARTITION;
}
void dds_qset_reliability
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(DDS_RELIABILITY_BEST_EFFORT, DDS_RELIABILITY_RELIABLE) dds_reliability_kind_t kind,
_In_range_(0, DDS_INFINITY) dds_duration_t max_blocking_time
)
{
if (qos) {
qos->reliability.kind = (nn_reliability_kind_t) kind;
qos->reliability.max_blocking_time = nn_to_ddsi_duration (max_blocking_time);
qos->present |= QP_RELIABILITY;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void dds_qset_transport_priority
(
_Inout_ dds_qos_t * __restrict qos,
_In_ int32_t value
)
{
if (qos) {
qos->transport_priority.value = value;
qos->present |= QP_TRANSPORT_PRIORITY;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void dds_qset_destination_order
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP,
DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP) dds_destination_order_kind_t kind
)
{
if (qos) {
qos->destination_order.kind = (nn_destination_order_kind_t) kind;
qos->present |= QP_DESTINATION_ORDER;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void dds_qset_writer_data_lifecycle
(
_Inout_ dds_qos_t * __restrict qos,
_In_ bool autodispose
)
{
if(qos) {
qos->writer_data_lifecycle.autodispose_unregistered_instances = autodispose;
qos->present |= QP_PRISMTECH_WRITER_DATA_LIFECYCLE;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void dds_qset_reader_data_lifecycle
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(0, DDS_INFINITY) dds_duration_t autopurge_nowriter_samples_delay,
_In_range_(0, DDS_INFINITY) dds_duration_t autopurge_disposed_samples_delay
)
{
if (qos) {
qos->reader_data_lifecycle.autopurge_nowriter_samples_delay = \
nn_to_ddsi_duration (autopurge_nowriter_samples_delay);
qos->reader_data_lifecycle.autopurge_disposed_samples_delay = \
nn_to_ddsi_duration (autopurge_disposed_samples_delay);
qos->present |= QP_PRISMTECH_READER_DATA_LIFECYCLE;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void dds_qset_durability_service
(
_Inout_ dds_qos_t * __restrict qos,
_In_range_(0, DDS_INFINITY) dds_duration_t service_cleanup_delay,
_In_range_(DDS_HISTORY_KEEP_LAST, DDS_HISTORY_KEEP_ALL) dds_history_kind_t history_kind,
_In_range_(>=, DDS_LENGTH_UNLIMITED) int32_t history_depth,
_In_range_(>=, DDS_LENGTH_UNLIMITED) int32_t max_samples,
_In_range_(>=, DDS_LENGTH_UNLIMITED) int32_t max_instances,
_In_range_(>=, DDS_LENGTH_UNLIMITED) int32_t max_samples_per_instance
)
{
if (qos) {
qos->durability_service.service_cleanup_delay = nn_to_ddsi_duration (service_cleanup_delay);
qos->durability_service.history.kind = (nn_history_kind_t) history_kind;
qos->durability_service.history.depth = history_depth;
qos->durability_service.resource_limits.max_samples = max_samples;
qos->durability_service.resource_limits.max_instances = max_instances;
qos->durability_service.resource_limits.max_samples_per_instance = max_samples_per_instance;
qos->present |= QP_DURABILITY_SERVICE;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
}
}
void dds_qget_userdata
(
_In_ const dds_qos_t * __restrict qos,
_Outptr_result_bytebuffer_maybenull_(*sz) void ** value,
_Out_ size_t * sz
)
{
if(!qos) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
return ;
}
if(!value) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument value is NULL");
return ;
}
if(!sz) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument sz is NULL");
return ;
}
dds_qos_data_copy_out (&qos->user_data, value, sz);
}
void dds_qget_topicdata
(
_In_ const dds_qos_t * __restrict qos,
_Outptr_result_bytebuffer_maybenull_(*sz) void ** value,
_Out_ size_t * sz
)
{
if(!qos) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
return ;
}
if(!value) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument value is NULL");
return ;
}
if(!sz) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument sz is NULL");
return ;
}
dds_qos_data_copy_out (&qos->topic_data, value, sz);
}
void dds_qget_groupdata
(
_In_ const dds_qos_t * __restrict qos,
_Outptr_result_bytebuffer_maybenull_(*sz) void ** value,
_Out_ size_t * sz
)
{
if(!qos) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
return ;
}
if(!value) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument value is NULL");
return ;
}
if(!sz) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument sz is NULL");
return ;
}
dds_qos_data_copy_out (&qos->group_data, value, sz);
}
void dds_qget_durability
(
_In_ const dds_qos_t * __restrict qos,
_Out_ dds_durability_kind_t *kind
)
{
if(!qos) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is NULL");
return ;
}
if(!kind) {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument kind is NULL");
return ;
}
*kind = (dds_durability_kind_t) qos->durability.kind;
}
void dds_qget_history
(
_In_ const dds_qos_t * __restrict qos,
_Out_opt_ dds_history_kind_t * kind,
_Out_opt_ int32_t *depth
)
{
if (qos) {
if (kind) *kind = (dds_history_kind_t) qos->history.kind;
if (depth) *depth = qos->history.depth;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
}
}
void dds_qget_resource_limits
(
_In_ const dds_qos_t * __restrict qos,
_Out_opt_ int32_t *max_samples,
_Out_opt_ int32_t *max_instances,
_Out_opt_ int32_t *max_samples_per_instance
)
{
if (qos) {
if (max_samples) *max_samples = qos->resource_limits.max_samples;
if (max_instances) *max_instances = qos->resource_limits.max_instances;
if (max_samples_per_instance) {
*max_samples_per_instance = qos->resource_limits.max_samples_per_instance;
}
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
}
}
void dds_qget_presentation
(
_In_ const dds_qos_t * __restrict qos,
_Out_opt_ dds_presentation_access_scope_kind_t *access_scope,
_Out_opt_ bool *coherent_access,
_Out_opt_ bool *ordered_access
)
{
if (qos) {
if (access_scope) *access_scope = (dds_presentation_access_scope_kind_t) qos->presentation.access_scope;
if (coherent_access) *coherent_access = qos->presentation.coherent_access;
if (ordered_access) *ordered_access = qos->presentation.ordered_access;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
}
}
void dds_qget_lifespan
(
_In_ const dds_qos_t * __restrict qos,
_Out_ dds_duration_t * lifespan
)
{
if(!qos){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
return ;
}
if(!lifespan){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument lifespan is NULL");
return ;
}
*lifespan = nn_from_ddsi_duration (qos->lifespan.duration);
}
void dds_qget_deadline
(
_In_ const dds_qos_t * __restrict qos,
_Out_ dds_duration_t * deadline
)
{
if(!qos){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
return ;
}
if(!deadline){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument deadline is NULL");
return ;
}
*deadline = nn_from_ddsi_duration (qos->deadline.deadline);
}
void dds_qget_latency_budget
(
_In_ const dds_qos_t * __restrict qos,
_Out_ dds_duration_t *duration
)
{
if(!qos){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
return ;
}
if(!duration){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument duration is NULL");
return ;
}
*duration = nn_from_ddsi_duration (qos->latency_budget.duration);
}
void dds_qget_ownership
(
_In_ const dds_qos_t * __restrict qos,
_Out_ dds_ownership_kind_t *kind
)
{
if(!qos){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
return ;
}
if(!kind){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument kind is NULL");
return ;
}
*kind = (dds_ownership_kind_t) qos->ownership.kind;
}
void dds_qget_ownership_strength
(
_In_ const dds_qos_t * __restrict qos,
_Out_ int32_t *value
)
{
if(!qos){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
return ;
}
if(!value){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument value is NULL");
return ;
}
*value = qos->ownership_strength.value;
}
void dds_qget_liveliness
(
_In_ const dds_qos_t * __restrict qos,
_Out_opt_ dds_liveliness_kind_t *kind,
_Out_opt_ dds_duration_t *lease_duration
)
{
if (qos) {
if (kind) *kind = (dds_liveliness_kind_t) qos->liveliness.kind;
if (lease_duration) *lease_duration = nn_from_ddsi_duration (qos->liveliness.lease_duration);
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
}
}
void dds_qget_time_based_filter
(
_In_ const dds_qos_t * __restrict qos,
_Out_ dds_duration_t *minimum_separation
)
{
if(!qos){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
return ;
}
if(!minimum_separation){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument minimum_separation is NULL");
return ;
}
*minimum_separation = nn_from_ddsi_duration (qos->time_based_filter.minimum_separation);
}
void dds_qget_partition
(
_In_ const dds_qos_t * __restrict qos,
_Out_ uint32_t *n,
_Outptr_opt_result_buffer_all_maybenull_(*n) char *** ps
)
{
size_t len;
uint32_t i;
if(!qos){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
return ;
}
if(!n){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument n is NULL");
return ;
}
*n = qos->partition.n;
if ( ps ) {
if ( qos->partition.n != 0 ) {
*ps = dds_alloc(sizeof(char*) * qos->partition.n);
for ( i = 0; i < qos->partition.n; i++ ) {
len = strlen(qos->partition.strs[i]) + 1;
(*ps)[i] = dds_alloc(len);
strncpy((*ps)[i], qos->partition.strs[i], len);
}
} else {
*ps = NULL;
}
}
}
void dds_qget_reliability
(
_In_ const dds_qos_t * __restrict qos,
_Out_opt_ dds_reliability_kind_t *kind,
_Out_opt_ dds_duration_t *max_blocking_time
)
{
if (qos) {
if (kind) *kind = (dds_reliability_kind_t) qos->reliability.kind;
if (max_blocking_time) *max_blocking_time = nn_from_ddsi_duration (qos->reliability.max_blocking_time);
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
}
}
void dds_qget_transport_priority
(
_In_ const dds_qos_t * __restrict qos,
_Out_ int32_t *value
)
{
if(!qos){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
return ;
}
if(!value){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument value is NULL");
return ;
}
*value = qos->transport_priority.value;
}
void dds_qget_destination_order
(
_In_ const dds_qos_t * __restrict qos,
_Out_ dds_destination_order_kind_t *kind
)
{
if(!qos){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
return ;
}
if(!kind){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument kind is NULL");
return ;
}
*kind = (dds_destination_order_kind_t) qos->destination_order.kind;
}
void dds_qget_writer_data_lifecycle
(
_In_ const dds_qos_t * __restrict qos,
_Out_ bool * autodispose
)
{
if(!qos){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
return ;
}
if(!autodispose){
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument autodispose is NULL");
return ;
}
*autodispose = qos->writer_data_lifecycle.autodispose_unregistered_instances;
}
void dds_qget_reader_data_lifecycle
(
_In_ const dds_qos_t * __restrict qos,
_Out_opt_ dds_duration_t *autopurge_nowriter_samples_delay,
_Out_opt_ dds_duration_t *autopurge_disposed_samples_delay
)
{
if (qos) {
if (autopurge_nowriter_samples_delay) {
*autopurge_nowriter_samples_delay = \
nn_from_ddsi_duration (qos->reader_data_lifecycle.autopurge_nowriter_samples_delay);
}
if (autopurge_disposed_samples_delay) {
*autopurge_disposed_samples_delay = \
nn_from_ddsi_duration (qos->reader_data_lifecycle.autopurge_disposed_samples_delay);
}
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
}
}
void dds_qget_durability_service
(
_In_ const dds_qos_t * qos,
_Out_opt_ dds_duration_t * service_cleanup_delay,
_Out_opt_ dds_history_kind_t * history_kind,
_Out_opt_ int32_t * history_depth,
_Out_opt_ int32_t * max_samples,
_Out_opt_ int32_t * max_instances,
_Out_opt_ int32_t * max_samples_per_instance
)
{
if (qos) {
if (service_cleanup_delay) *service_cleanup_delay = nn_from_ddsi_duration (qos->durability_service.service_cleanup_delay);
if (history_kind) *history_kind = (dds_history_kind_t) qos->durability_service.history.kind;
if (history_depth) *history_depth = qos->durability_service.history.depth;
if (max_samples) *max_samples = qos->durability_service.resource_limits.max_samples;
if (max_instances) *max_instances = qos->durability_service.resource_limits.max_instances;
if (max_samples_per_instance) *max_samples_per_instance = qos->durability_service.resource_limits.max_samples_per_instance;
} else {
DDS_ERROR(DDS_RETCODE_BAD_PARAMETER, "Argument qos is NULL");
}
}

View file

@ -0,0 +1,60 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include "dds__entity.h"
#include "dds__reader.h"
#include "dds__topic.h"
#include "dds__querycond.h"
#include "dds__readcond.h"
#include "dds__err.h"
#include "ddsi/ddsi_ser.h"
#include "dds__report.h"
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER)
DDS_EXPORT dds_entity_t
dds_create_querycondition(
_In_ dds_entity_t reader,
_In_ uint32_t mask,
_In_ dds_querycondition_filter_fn filter)
{
dds_entity_t topic;
dds_entity_t hdl;
dds__retcode_t rc;
dds_reader *r;
dds_topic *t;
DDS_REPORT_STACK();
rc = dds_reader_lock(reader, &r);
if (rc == DDS_RETCODE_OK) {
dds_readcond *cond = dds_create_readcond(r, DDS_KIND_COND_QUERY, mask);
assert(cond);
hdl = cond->m_entity.m_hdl;
cond->m_query.m_filter = filter;
topic = r->m_topic->m_entity.m_hdl;
dds_reader_unlock(r);
rc = dds_topic_lock(topic, &t);
if (rc == DDS_RETCODE_OK) {
if (t->m_stopic->filter_sample == NULL) {
t->m_stopic->filter_sample = dds_alloc(t->m_descriptor->m_size);
}
dds_topic_unlock(t);
} else {
(void)dds_delete(hdl);
hdl = DDS_ERRNO(rc, "Error occurred on locking topic");
}
} else {
hdl = DDS_ERRNO(rc, "Error occurred on locking reader");
}
DDS_REPORT_FLUSH(hdl <= 0);
return hdl;
}

View file

@ -0,0 +1,865 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include "dds__entity.h"
#include "dds__reader.h"
#include "dds__tkmap.h"
#include "dds__rhc.h"
#include "dds__err.h"
#include "ddsi/q_thread.h"
#include "ddsi/q_ephash.h"
#include "ddsi/q_entity.h"
#include "dds__report.h"
static _Check_return_ dds__retcode_t
dds_read_lock(
_In_ dds_entity_t hdl,
_Out_ dds_reader **reader,
_Out_ dds_readcond **condition,
_In_ bool only_reader)
{
dds__retcode_t rc = hdl;
assert(reader);
assert(condition);
*reader = NULL;
*condition = NULL;
rc = dds_entity_lock(hdl, DDS_KIND_READER, (dds_entity**)reader);
if (rc == DDS_RETCODE_ILLEGAL_OPERATION) {
if (!only_reader) {
if ((dds_entity_kind(hdl) == DDS_KIND_COND_READ ) || (dds_entity_kind(hdl) == DDS_KIND_COND_QUERY) ){
rc = dds_entity_lock(hdl, DDS_KIND_DONTCARE, (dds_entity**)condition);
if (rc == DDS_RETCODE_OK) {
dds_entity *parent = ((dds_entity*)*condition)->m_parent;
assert(parent);
rc = dds_entity_lock(parent->m_hdl, DDS_KIND_READER, (dds_entity**)reader);
if (rc != DDS_RETCODE_OK) {
dds_entity_unlock((dds_entity*)*condition);
DDS_ERROR(rc, "Failed to lock condition reader.");
}
} else {
DDS_ERROR(rc, "Failed to lock condition.");
}
} else {
DDS_ERROR(rc, "Given entity is not a reader nor a condition.");
}
} else {
DDS_ERROR(rc, "Given entity is not a reader.");
}
} else if (rc != DDS_RETCODE_OK) {
DDS_ERROR(rc, "Failed to lock reader.");
}
return rc;
}
static void
dds_read_unlock(
_In_ dds_reader *reader,
_In_ dds_readcond *condition)
{
assert(reader);
dds_entity_unlock((dds_entity*)reader);
if (condition) {
dds_entity_unlock((dds_entity*)condition);
}
}
/*
dds_read_impl: Core read/take function. Usually maxs is size of buf and si
into which samples/status are written, when set to zero is special case
indicating that size set from number of samples in cache and also that cache
has been locked. This is used to support C++ API reading length unlimited
which is interpreted as "all relevant samples in cache".
*/
static dds_return_t
dds_read_impl(
_In_ bool take,
_In_ dds_entity_t reader_or_condition,
_Inout_ void **buf,
_In_ size_t bufsz,
_In_ uint32_t maxs,
_Out_ dds_sample_info_t *si,
_In_ uint32_t mask,
_In_ dds_instance_handle_t hand,
_In_ bool lock,
_In_ bool only_reader)
{
uint32_t i;
dds_return_t ret = DDS_RETCODE_OK;
dds__retcode_t rc;
struct dds_reader * rd;
struct dds_readcond * cond;
struct thread_state1 * const thr = lookup_thread_state ();
const bool asleep = !vtime_awake_p (thr->vtime);
if (asleep) {
thread_state_awake (thr);
}
if (buf == NULL) {
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "The provided buffer is NULL");
goto fail;
}
if (si == NULL) {
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Provided pointer to an array of dds_sample_info_t is NULL");
goto fail;
}
if (maxs == 0) {
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "The maximum number of samples to read is zero");
goto fail;
}
if (bufsz == 0) {
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "The size of buffer is zero");
goto fail;
}
if (bufsz < maxs) {
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "The provided size of buffer is smaller than the maximum number of samples to read");
goto fail;
}
rc = dds_read_lock(reader_or_condition, &rd, &cond, only_reader);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking entity");
goto fail;
}
if (hand != DDS_HANDLE_NIL) {
if (dds_tkmap_find_by_id(gv.m_tkmap, hand) == NULL) {
ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET, "Could not find instance");
dds_read_unlock(rd, cond);
goto fail;
}
}
/* Allocate samples if not provided (assuming all or none provided) */
if (buf[0] == NULL) {
char * loan;
const size_t sz = rd->m_topic->m_descriptor->m_size;
const uint32_t loan_size = (uint32_t) (sz * maxs);
/* Allocate, use or reallocate loan cached on reader */
if (rd->m_loan_out) {
loan = dds_alloc (loan_size);
} else {
if (rd->m_loan) {
if (rd->m_loan_size < loan_size) {
rd->m_loan = dds_realloc_zero (rd->m_loan, loan_size);
rd->m_loan_size = loan_size;
}
} else {
rd->m_loan = dds_alloc (loan_size);
rd->m_loan_size = loan_size;
}
loan = rd->m_loan;
rd->m_loan_out = true;
}
for (i = 0; i < maxs; i++) {
buf[i] = loan;
loan += sz;
}
}
if (take) {
ret = (dds_return_t)dds_rhc_take(rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond);
} else {
ret = (dds_return_t)dds_rhc_read(rd->m_rd->rhc, lock, buf, si, maxs, mask, hand, cond);
}
/* read/take resets data available status */
dds_entity_status_reset(rd, DDS_DATA_AVAILABLE_STATUS);
/* reset DATA_ON_READERS status on subscriber after successful read/take */
if (dds_entity_kind(((dds_entity*)rd)->m_parent->m_hdl) == DDS_KIND_SUBSCRIBER) {
dds_entity_status_reset(((dds_entity*)rd)->m_parent, DDS_DATA_ON_READERS_STATUS);
}
dds_read_unlock(rd, cond);
fail:
if (asleep) {
thread_state_asleep (thr);
}
return ret;
}
static dds_return_t
dds_readcdr_impl(
_In_ bool take,
_In_ dds_entity_t reader_or_condition,
_Out_ struct serdata ** buf,
_In_ uint32_t maxs,
_Out_ dds_sample_info_t * si,
_In_ uint32_t mask,
_In_ dds_instance_handle_t hand,
_In_ bool lock)
{
dds_return_t ret = DDS_RETCODE_OK;
dds__retcode_t rc;
struct dds_reader * rd;
struct dds_readcond * cond;
struct thread_state1 * const thr = lookup_thread_state ();
const bool asleep = !vtime_awake_p (thr->vtime);
assert (take);
assert (buf);
assert (si);
assert (hand == DDS_HANDLE_NIL);
assert (maxs > 0);
if (asleep)
{
thread_state_awake (thr);
}
rc = dds_read_lock(reader_or_condition, &rd, &cond, false);
if (rc >= DDS_RETCODE_OK) {
ret = dds_rhc_takecdr
(
rd->m_rd->rhc, lock, buf, si, maxs,
mask & DDS_ANY_SAMPLE_STATE,
mask & DDS_ANY_VIEW_STATE,
mask & DDS_ANY_INSTANCE_STATE,
hand
);
/* read/take resets data available status */
dds_entity_status_reset(rd, DDS_DATA_AVAILABLE_STATUS);
/* reset DATA_ON_READERS status on subscriber after successful read/take */
if (dds_entity_kind(((dds_entity*)rd)->m_parent->m_hdl) == DDS_KIND_SUBSCRIBER)
{
dds_entity_status_reset(((dds_entity*)rd)->m_parent, DDS_DATA_ON_READERS_STATUS);
}
dds_read_unlock(rd, cond);
} else {
ret = DDS_ERRNO(rc, "Error occurred on locking entity");
}
if (asleep)
{
thread_state_asleep (thr);
}
return ret;
}
_Pre_satisfies_(((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY ))
dds_return_t
dds_read(
_In_ dds_entity_t rd_or_cnd,
_Inout_ void ** buf,
_Out_ dds_sample_info_t * si,
_In_ size_t bufsz,
_In_ uint32_t maxs)
{
bool lock = true;
dds_return_t ret;
DDS_REPORT_STACK();
if (maxs == DDS_READ_WITHOUT_LOCK) {
lock = false;
/* Use a more sensible maxs, so use bufsz instead.
* CHAM-306 will remove this ugly piece of code. */
maxs = (uint32_t)bufsz;
}
ret = dds_read_impl (false, rd_or_cnd, buf, bufsz, maxs, si, NO_STATE_MASK_SET, DDS_HANDLE_NIL, lock, false);
DDS_REPORT_FLUSH(ret < 0);
return ret;
}
_Pre_satisfies_(((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY ))
dds_return_t
dds_read_wl(
_In_ dds_entity_t rd_or_cnd,
_Inout_ void ** buf,
_Out_ dds_sample_info_t * si,
_In_ uint32_t maxs)
{
bool lock = true;
dds_return_t ret;
DDS_REPORT_STACK();
if (maxs == DDS_READ_WITHOUT_LOCK) {
lock = false;
/* Use a more sensible maxs. Just an arbitrarily number.
* CHAM-306 will remove this ugly piece of code. */
maxs = 100;
}
ret = dds_read_impl (false, rd_or_cnd, buf, maxs, maxs, si, NO_STATE_MASK_SET, DDS_HANDLE_NIL, lock, false);
DDS_REPORT_FLUSH(ret < 0);
return ret;
}
_Pre_satisfies_(((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY ))
dds_return_t
dds_read_mask(
_In_ dds_entity_t rd_or_cnd,
_Inout_ void ** buf,
_Out_ dds_sample_info_t * si,
_In_ size_t bufsz,
_In_ uint32_t maxs,
_In_ uint32_t mask)
{
bool lock = true;
dds_return_t ret;
DDS_REPORT_STACK();
if (maxs == DDS_READ_WITHOUT_LOCK) {
lock = false;
/* Use a more sensible maxs, so use bufsz instead.
* CHAM-306 will remove this ugly piece of code. */
maxs = (uint32_t)bufsz;
}
ret = dds_read_impl (false, rd_or_cnd, buf, bufsz, maxs, si, mask, DDS_HANDLE_NIL, lock, false);
DDS_REPORT_FLUSH(ret < 0);
return ret;
}
_Pre_satisfies_(((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY ))
dds_return_t
dds_read_mask_wl(
_In_ dds_entity_t rd_or_cnd,
_Inout_ void ** buf,
_Out_ dds_sample_info_t * si,
_In_ uint32_t maxs,
_In_ uint32_t mask)
{
bool lock = true;
dds_return_t ret;
DDS_REPORT_STACK();
if (maxs == DDS_READ_WITHOUT_LOCK) {
lock = false;
/* Use a more sensible maxs. Just an arbitrarily number.
* CHAM-306 will remove this ugly piece of code. */
maxs = 100;
}
ret = dds_read_impl (false, rd_or_cnd, buf, maxs, maxs, si, mask, DDS_HANDLE_NIL, lock, false);
DDS_REPORT_FLUSH(ret < 0 );
return ret;
}
_Pre_satisfies_(((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY ))
dds_return_t
dds_read_instance(
_In_ dds_entity_t rd_or_cnd,
_Inout_ void **buf,
_Out_ dds_sample_info_t *si,
_In_ size_t bufsz,
_In_ uint32_t maxs,
_In_ dds_instance_handle_t handle)
{
dds_return_t ret = DDS_RETCODE_OK;
bool lock = true;
DDS_REPORT_STACK();
if (handle == DDS_HANDLE_NIL) {
ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET, "DDS_HANDLE_NIL was provided");
goto fail;
}
if (maxs == DDS_READ_WITHOUT_LOCK) {
lock = false;
/* Use a more sensible maxs. Just an arbitrarily number.
* CHAM-306 will remove this ugly piece of code. */
maxs = 100;
}
ret = dds_read_impl(false, rd_or_cnd, buf, bufsz, maxs, si, NO_STATE_MASK_SET, handle, lock, false);
fail:
DDS_REPORT_FLUSH(ret < 0 );
return ret;
}
_Pre_satisfies_(((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY ))
dds_return_t
dds_read_instance_wl(
_In_ dds_entity_t rd_or_cnd,
_Inout_ void **buf,
_Out_ dds_sample_info_t *si,
_In_ uint32_t maxs,
_In_ dds_instance_handle_t handle)
{
dds_return_t ret = DDS_RETCODE_OK;
bool lock = true;
DDS_REPORT_STACK();
if (handle == DDS_HANDLE_NIL) {
ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET, "DDS_HANDLE_NIL was provided");
goto fail;
}
if (maxs == DDS_READ_WITHOUT_LOCK) {
lock = false;
/* Use a more sensible maxs. Just an arbitrarily number.
* CHAM-306 will remove this ugly piece of code. */
maxs = 100;
}
ret = dds_read_impl(false, rd_or_cnd, buf, maxs, maxs, si, NO_STATE_MASK_SET, handle, lock, false);
fail:
DDS_REPORT_FLUSH(ret < 0);
return ret;
}
_Pre_satisfies_(((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY ))
dds_return_t
dds_read_instance_mask(
_In_ dds_entity_t rd_or_cnd,
_Inout_ void **buf,
_Out_ dds_sample_info_t *si,
_In_ size_t bufsz,
_In_ uint32_t maxs,
_In_ dds_instance_handle_t handle,
_In_ uint32_t mask)
{
dds_return_t ret = DDS_RETCODE_OK;
bool lock = true;
DDS_REPORT_STACK();
if (handle == DDS_HANDLE_NIL) {
ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET, "DDS_HANDLE_NIL was provided");
goto fail;
}
if (maxs == DDS_READ_WITHOUT_LOCK) {
lock = false;
/* Use a more sensible maxs. Just an arbitrarily number.
* CHAM-306 will remove this ugly piece of code. */
maxs = 100;
}
ret = dds_read_impl(false, rd_or_cnd, buf, bufsz, maxs, si, mask, handle, lock, false);
fail:
DDS_REPORT_FLUSH(ret < 0);
return ret;
}
_Pre_satisfies_(((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY ))
dds_return_t
dds_read_instance_mask_wl(
_In_ dds_entity_t rd_or_cnd,
_Inout_ void **buf,
_Out_ dds_sample_info_t *si,
_In_ uint32_t maxs,
_In_ dds_instance_handle_t handle,
_In_ uint32_t mask)
{
dds_return_t ret = DDS_RETCODE_OK;
bool lock = true;
DDS_REPORT_STACK();
if (handle == DDS_HANDLE_NIL) {
ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET, "DDS_HANDLE_NIL was provided");
goto fail;
}
if (maxs == DDS_READ_WITHOUT_LOCK) {
lock = false;
/* Use a more sensible maxs. Just an arbitrarily number.
* CHAM-306 will remove this ugly piece of code. */
maxs = 100;
}
ret = dds_read_impl(false, rd_or_cnd, buf, maxs, maxs, si, mask, handle, lock, false);
fail:
DDS_REPORT_FLUSH(ret < 0);
return ret;
}
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER )
dds_return_t
dds_read_next(
_In_ dds_entity_t reader,
_Inout_ void **buf,
_Out_ dds_sample_info_t *si)
{
uint32_t mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE;
dds_return_t ret;
DDS_REPORT_STACK();
ret = dds_read_impl (false, reader, buf, 1u, 1u, si, mask, DDS_HANDLE_NIL, true, true);
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER )
dds_return_t
dds_read_next_wl(
_In_ dds_entity_t reader,
_Inout_ void **buf,
_Out_ dds_sample_info_t *si)
{
uint32_t mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE;
dds_return_t ret;
DDS_REPORT_STACK();
ret = dds_read_impl (false, reader, buf, 1u, 1u, si, mask, DDS_HANDLE_NIL, true, true);
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_(((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY ))
dds_return_t
dds_take(
_In_ dds_entity_t rd_or_cnd,
_Inout_ void ** buf,
_Out_ dds_sample_info_t * si,
_In_ size_t bufsz,
_In_ uint32_t maxs)
{
bool lock = true;
dds_return_t ret;
DDS_REPORT_STACK();
if (maxs == DDS_READ_WITHOUT_LOCK) {
lock = false;
/* Use a more sensible maxs, so use bufsz instead.
* CHAM-306 will remove this ugly piece of code. */
maxs = (uint32_t)bufsz;
}
ret = dds_read_impl (true, rd_or_cnd, buf, bufsz, maxs, si, NO_STATE_MASK_SET, DDS_HANDLE_NIL, lock, false);
DDS_REPORT_FLUSH(ret < 0);
return ret;
}
_Pre_satisfies_(((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY ))
dds_return_t
dds_take_wl(
_In_ dds_entity_t rd_or_cnd,
_Inout_ void ** buf,
_Out_ dds_sample_info_t * si,
_In_ uint32_t maxs)
{
bool lock = true;
dds_return_t ret;
DDS_REPORT_STACK();
if (maxs == DDS_READ_WITHOUT_LOCK) {
lock = false;
/* Use a more sensible maxs. Just an arbitrarily number.
* CHAM-306 will remove this ugly piece of code. */
maxs = 100;
}
ret = dds_read_impl (true, rd_or_cnd, buf, maxs, maxs, si, NO_STATE_MASK_SET, DDS_HANDLE_NIL, lock, false);
DDS_REPORT_FLUSH(ret < 0);
return ret;
}
_Pre_satisfies_(((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY ))
dds_return_t
dds_take_mask(
_In_ dds_entity_t rd_or_cnd,
_Inout_ void ** buf,
_Out_ dds_sample_info_t * si,
_In_ size_t bufsz,
_In_ uint32_t maxs,
_In_ uint32_t mask)
{
bool lock = true;
dds_return_t ret;
DDS_REPORT_STACK();
if (maxs == DDS_READ_WITHOUT_LOCK) {
lock = false;
/* Use a more sensible maxs, so use bufsz instead.
* CHAM-306 will remove this ugly piece of code. */
maxs = (uint32_t)bufsz;
}
ret = dds_read_impl (true, rd_or_cnd, buf, bufsz, maxs, si, mask, DDS_HANDLE_NIL, lock, false);
DDS_REPORT_FLUSH(ret < 0);
return ret;
}
_Pre_satisfies_(((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY ))
dds_return_t
dds_take_mask_wl(
_In_ dds_entity_t rd_or_cnd,
_Inout_ void ** buf,
_Out_ dds_sample_info_t * si,
_In_ uint32_t maxs,
_In_ uint32_t mask)
{
bool lock = true;
dds_return_t ret;
DDS_REPORT_STACK();
if (maxs == DDS_READ_WITHOUT_LOCK) {
lock = false;
/* Use a more sensible maxs. Just an arbitrarily number.
* CHAM-306 will remove this ugly piece of code. */
maxs = 100;
}
ret = dds_read_impl (true, rd_or_cnd, buf, maxs, maxs, si, mask, DDS_HANDLE_NIL, lock, false);
DDS_REPORT_FLUSH(ret < 0);
return ret;
}
int
dds_takecdr(
dds_entity_t rd_or_cnd,
struct serdata **buf,
uint32_t maxs,
dds_sample_info_t *si,
uint32_t mask)
{
bool lock = true;
if (maxs == DDS_READ_WITHOUT_LOCK) {
lock = false;
/* Use a more sensible maxs. Just an arbitrarily number.
* CHAM-306 will remove this ugly piece of code. */
maxs = 100;
}
return dds_readcdr_impl (true, rd_or_cnd, buf, maxs, si, mask, DDS_HANDLE_NIL, lock);
}
_Pre_satisfies_(((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY ))
dds_return_t
dds_take_instance(
_In_ dds_entity_t rd_or_cnd,
_Inout_ void **buf,
_Out_ dds_sample_info_t *si,
_In_ size_t bufsz,
_In_ uint32_t maxs,
_In_ dds_instance_handle_t handle)
{
dds_return_t ret = DDS_RETCODE_OK;
bool lock = true;
DDS_REPORT_STACK();
if (handle == DDS_HANDLE_NIL) {
ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET, "DDS_HANDLE_NIL was provided");
goto fail;
}
if (maxs == DDS_READ_WITHOUT_LOCK) {
lock = false;
/* Use a more sensible maxs. Just an arbitrarily number.
* CHAM-306 will remove this ugly piece of code. */
maxs = 100;
}
ret = dds_read_impl(true, rd_or_cnd, buf, bufsz, maxs, si, NO_STATE_MASK_SET, handle, lock, false);
fail:
DDS_REPORT_FLUSH(ret < 0);
return ret;
}
_Pre_satisfies_(((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY ))
dds_return_t
dds_take_instance_wl(
_In_ dds_entity_t rd_or_cnd,
_Inout_ void **buf,
_Out_ dds_sample_info_t *si,
_In_ uint32_t maxs,
_In_ dds_instance_handle_t handle)
{
dds_return_t ret = DDS_RETCODE_OK;
bool lock = true;
DDS_REPORT_STACK();
if (handle == DDS_HANDLE_NIL) {
ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET, "DDS_HANDLE_NIL was provided");
goto fail;
}
if (maxs == DDS_READ_WITHOUT_LOCK) {
lock = false;
/* Use a more sensible maxs. Just an arbitrarily number.
* CHAM-306 will remove this ugly piece of code. */
maxs = 100;
}
ret = dds_read_impl(true, rd_or_cnd, buf, maxs, maxs, si, NO_STATE_MASK_SET, handle, lock, false);
fail:
DDS_REPORT_FLUSH(ret < 0);
return ret;
}
_Pre_satisfies_(((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY ))
dds_return_t
dds_take_instance_mask(
_In_ dds_entity_t rd_or_cnd,
_Inout_ void **buf,
_Out_ dds_sample_info_t *si,
_In_ size_t bufsz,
_In_ uint32_t maxs,
_In_ dds_instance_handle_t handle,
_In_ uint32_t mask)
{
dds_return_t ret = DDS_RETCODE_OK;
bool lock = true;
DDS_REPORT_STACK();
if (handle == DDS_HANDLE_NIL) {
ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET, "DDS_HANDLE_NIL was provided");
goto fail;
}
if (maxs == DDS_READ_WITHOUT_LOCK) {
lock = false;
/* Use a more sensible maxs. Just an arbitrarily number.
* CHAM-306 will remove this ugly piece of code. */
maxs = 100;
}
ret = dds_read_impl(true, rd_or_cnd, buf, bufsz, maxs, si, mask, handle, lock, false);
fail:
DDS_REPORT_FLUSH(ret < 0);
return ret;
}
_Pre_satisfies_(((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((rd_or_cnd & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY ))
dds_return_t
dds_take_instance_mask_wl(
_In_ dds_entity_t rd_or_cnd,
_Inout_ void **buf,
_Out_ dds_sample_info_t *si,
_In_ uint32_t maxs,
_In_ dds_instance_handle_t handle,
_In_ uint32_t mask)
{
dds_return_t ret = DDS_RETCODE_OK;
bool lock = true;
DDS_REPORT_STACK();
if (handle == DDS_HANDLE_NIL) {
ret = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET, "DDS_HANDLE_NIL was provided");
goto fail;
}
if (maxs == DDS_READ_WITHOUT_LOCK) {
lock = false;
/* Use a more sensible maxs. Just an arbitrarily number.
* CHAM-306 will remove this ugly piece of code. */
maxs = 100;
}
ret = dds_read_impl(true, rd_or_cnd, buf, maxs, maxs, si, mask, handle, lock, false);
fail:
DDS_REPORT_FLUSH(ret < 0);
return ret;
}
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER )
dds_return_t
dds_take_next(
_In_ dds_entity_t reader,
_Inout_ void **buf,
_Out_ dds_sample_info_t *si)
{
uint32_t mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE;
dds_return_t ret;
DDS_REPORT_STACK();
ret = dds_read_impl (true, reader, buf, 1u, 1u, si, mask, DDS_HANDLE_NIL, true, true);
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER )
dds_return_t
dds_take_next_wl(
_In_ dds_entity_t reader,
_Inout_ void **buf,
_Out_ dds_sample_info_t *si)
{
uint32_t mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE;
dds_return_t ret;
DDS_REPORT_STACK();
ret = dds_read_impl (true, reader, buf, 1u, 1u, si, mask, DDS_HANDLE_NIL, true, true);
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_(((reader_or_condition & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) ||\
((reader_or_condition & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((reader_or_condition & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY ))
_Must_inspect_result_ dds_return_t
dds_return_loan(
_In_ dds_entity_t reader_or_condition,
_Inout_updates_(bufsz) void **buf,
_In_ size_t bufsz)
{
dds__retcode_t rc;
const dds_topic_descriptor_t * desc;
dds_reader *rd;
dds_readcond *cond;
dds_return_t ret = DDS_RETCODE_OK;
DDS_REPORT_STACK();
if (!buf ) {
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument buf is NULL");
goto fail;
}
if(*buf == NULL && bufsz > 0){
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument buf is NULL");
goto fail;
}
rc = dds_read_lock(reader_or_condition, &rd, &cond, false);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking entity");
goto fail;
}
desc = rd->m_topic->m_descriptor;
/* Only free sample contents if they have been allocated */
if (desc->m_flagset & DDS_TOPIC_NO_OPTIMIZE) {
size_t i = 0;
for (i = 0; i < bufsz; i++) {
dds_sample_free(buf[i], desc, DDS_FREE_CONTENTS);
}
}
/* If possible return loan buffer to reader */
if (rd->m_loan != 0 && (buf[0] == rd->m_loan)) {
rd->m_loan_out = false;
memset (rd->m_loan, 0, rd->m_loan_size);
buf[0] = NULL;
}
dds_read_unlock(rd, cond);
fail:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}

View file

@ -0,0 +1,129 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include "dds__reader.h"
#include "dds__readcond.h"
#include "dds__rhc.h"
#include "dds__entity.h"
#include "dds__err.h"
#include "ddsi/q_ephash.h"
#include "ddsi/q_entity.h"
#include "ddsi/q_thread.h"
#include "dds__report.h"
static dds_return_t
dds_readcond_delete(
dds_entity *e)
{
dds_rhc_remove_readcondition((dds_readcond*)e);
return DDS_RETCODE_OK;
}
_Must_inspect_result_ dds_readcond*
dds_create_readcond(
_In_ dds_reader *rd,
_In_ dds_entity_kind_t kind,
_In_ uint32_t mask)
{
dds_readcond * cond = dds_alloc(sizeof(*cond));
assert(kind == DDS_KIND_COND_READ || kind == DDS_KIND_COND_QUERY);
cond->m_entity.m_hdl = dds_entity_init(&cond->m_entity, (dds_entity*)rd, kind, NULL, NULL, 0);
cond->m_entity.m_deriver.delete = dds_readcond_delete;
cond->m_rhc = rd->m_rd->rhc;
cond->m_sample_states = mask & DDS_ANY_SAMPLE_STATE;
cond->m_view_states = mask & DDS_ANY_VIEW_STATE;
cond->m_instance_states = mask & DDS_ANY_INSTANCE_STATE;
cond->m_rd_guid = ((dds_entity*)rd)->m_guid;
dds_rhc_add_readcondition (cond);
return cond;
}
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER)
_Must_inspect_result_ dds_entity_t
dds_create_readcondition(
_In_ dds_entity_t reader,
_In_ uint32_t mask)
{
dds_entity_t hdl;
dds_reader * rd;
dds__retcode_t rc;
DDS_REPORT_STACK();
rc = dds_reader_lock(reader, &rd);
if (rc == DDS_RETCODE_OK) {
dds_readcond *cond = dds_create_readcond(rd, DDS_KIND_COND_READ, mask);
assert(cond);
hdl = cond->m_entity.m_hdl;
dds_reader_unlock(rd);
} else {
hdl = DDS_ERRNO(rc, "Error occurred on locking reader");
}
DDS_REPORT_FLUSH(hdl <= 0);
return hdl;
}
_Pre_satisfies_(((condition & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((condition & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY) )
dds_entity_t
dds_get_datareader(
_In_ dds_entity_t condition)
{
dds_entity_t hdl;
DDS_REPORT_STACK();
if (dds_entity_kind(condition) == DDS_KIND_COND_READ) {
hdl = dds_get_parent(condition);
} else if (dds_entity_kind(condition) == DDS_KIND_COND_QUERY) {
hdl = dds_get_parent(condition);
} else {
hdl = DDS_ERRNO(dds_valid_hdl(condition, DDS_KIND_COND_READ), "Argument condition is not valid");
}
DDS_REPORT_FLUSH(hdl <= 0);
return hdl;
}
_Pre_satisfies_(((condition & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((condition & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY) )
_Check_return_ dds_return_t
dds_get_mask(
_In_ dds_entity_t condition,
_Out_ uint32_t *mask)
{
dds_return_t ret;
dds_readcond *cond;
dds__retcode_t rc;
DDS_REPORT_STACK();
if (mask != NULL) {
*mask = 0;
if ((dds_entity_kind(condition) == DDS_KIND_COND_READ ) ||
(dds_entity_kind(condition) == DDS_KIND_COND_QUERY) ){
rc = dds_entity_lock(condition, DDS_KIND_DONTCARE, (dds_entity**)&cond);
if (rc == DDS_RETCODE_OK) {
*mask = (cond->m_sample_states | cond->m_view_states | cond->m_instance_states);
dds_entity_unlock((dds_entity*)cond);
ret = DDS_RETCODE_OK;
} else{
ret = DDS_ERRNO(rc, "Error occurred on locking condition");
}
} else {
ret = DDS_ERRNO(dds_valid_hdl(condition, DDS_KIND_COND_READ), "Argument condition is not valid");
}
} else {
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument mask is NULL");
}
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}

View file

@ -0,0 +1,791 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include "ddsc/dds.h"
#include "dds__subscriber.h"
#include "dds__reader.h"
#include "dds__listener.h"
#include "dds__qos.h"
#include "dds__init.h"
#include "dds__rhc.h"
#include "dds__err.h"
#include "ddsi/q_entity.h"
#include "ddsi/q_thread.h"
#include "dds__report.h"
#include "dds__builtin.h"
#include "ddsc/ddsc_project.h"
#include <string.h>
#include "os/os.h"
#define DDS_READER_STATUS_MASK \
DDS_SAMPLE_REJECTED_STATUS |\
DDS_LIVELINESS_CHANGED_STATUS |\
DDS_REQUESTED_DEADLINE_MISSED_STATUS |\
DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS |\
DDS_DATA_AVAILABLE_STATUS |\
DDS_SAMPLE_LOST_STATUS |\
DDS_SUBSCRIPTION_MATCHED_STATUS
static dds_return_t
dds_reader_instance_hdl(
dds_entity *e,
dds_instance_handle_t *i)
{
assert(e);
assert(i);
*i = (dds_instance_handle_t)reader_instance_id(&e->m_guid);
return DDS_RETCODE_OK;
}
static dds_return_t
dds_reader_close(
dds_entity *e)
{
dds__retcode_t rc;
dds_return_t ret = DDS_RETCODE_OK;
struct thread_state1 * const thr = lookup_thread_state();
const bool asleep = !vtime_awake_p(thr->vtime);
assert(e);
assert(thr);
if (asleep) {
thread_state_awake(thr);
}
if (delete_reader(&e->m_guid) != 0) {
rc = DDS_RETCODE_ERROR;
ret = DDS_ERRNO(rc, "Internal error");
}
if (asleep) {
thread_state_asleep(thr);
}
return ret;
}
static dds_return_t
dds_reader_delete(
dds_entity *e)
{
dds_reader *rd = (dds_reader*)e;
dds_return_t ret;
assert(e);
ret = dds_delete(rd->m_topic->m_entity.m_hdl);
if(ret == DDS_RETCODE_OK){
ret = dds_delete_impl(e->m_parent->m_hdl, true);
if(dds_err_nr(ret) == DDS_RETCODE_ALREADY_DELETED){
ret = DDS_RETCODE_OK;
}
}
dds_free(rd->m_loan);
return ret;
}
static dds_return_t
dds_reader_qos_validate(
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = DDS_RETCODE_OK;
assert(qos);
/* Check consistency. */
if(!dds_qos_validate_common(qos)) {
ret = DDS_ERRNO(DDS_RETCODE_ERROR, "Argument Qos is not valid");
}
if((qos->present & QP_USER_DATA) && !(validate_octetseq (&qos->user_data))) {
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "User data policy is inconsistent and caused an error");
}
if((qos->present & QP_PRISMTECH_READER_DATA_LIFECYCLE) && (validate_reader_data_lifecycle (&qos->reader_data_lifecycle) != 0)) {
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Prismtech reader data lifecycle policy is inconsistent and caused an error");
}
if((qos->present & QP_TIME_BASED_FILTER) && (validate_duration (&qos->time_based_filter.minimum_separation) != 0)) {
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Time based filter policy is inconsistent and caused an error");
}
if((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && (validate_history_and_resource_limits (&qos->history, &qos->resource_limits) != 0)) {
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "History and resource limits policy is inconsistent and caused an error");
}
if((qos->present & QP_TIME_BASED_FILTER) && (qos->present & QP_DEADLINE) && !(validate_deadline_and_timebased_filter (qos->deadline.deadline, qos->time_based_filter.minimum_separation))) {
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Time based filter and deadline policy is inconsistent and caused an error");
}
if(ret == DDS_RETCODE_OK && enabled) {
ret = dds_qos_validate_mutable_common(qos);
}
return ret;
}
static dds_return_t
dds_reader_qos_set(
dds_entity *e,
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = dds_reader_qos_validate(qos, enabled);
if (ret == DDS_RETCODE_OK) {
if (enabled) {
/* TODO: CHAM-95: DDSI does not support changing QoS policies. */
ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED, DDSC_PROJECT_NAME" does not support changing QoS policies");
}
}
return ret;
}
static dds_return_t
dds_reader_status_validate(
uint32_t mask)
{
return (mask & ~(DDS_READER_STATUS_MASK)) ?
DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Invalid status mask") :
DDS_RETCODE_OK;
}
void
dds_reader_status_cb(
void *entity,
const status_cb_data_t *data)
{
dds_reader *rd;
dds__retcode_t rc;
void *metrics = NULL;
DDS_REPORT_STACK();
/* When data is NULL, it means that the DDSI reader is deleted. */
if (data == NULL) {
/* Release the initial claim that was done during the create. This
* will indicate that further API deletion is now possible. */
ut_handle_release(((dds_entity*)entity)->m_hdl, ((dds_entity*)entity)->m_hdllink);
return;
}
if (dds_reader_lock(((dds_entity*)entity)->m_hdl, &rd) != DDS_RETCODE_OK) {
/* There's a deletion or closing going on. */
DDS_REPORT_FLUSH(false);
return;
}
assert(rd == entity);
/* Reset the status for possible Listener call.
* When a listener is not called, the status will be set (again). */
dds_entity_status_reset(entity, data->status);
/* Update status metrics. */
switch (data->status) {
case DDS_REQUESTED_DEADLINE_MISSED_STATUS: {
rd->m_requested_deadline_missed_status.total_count++;
rd->m_requested_deadline_missed_status.total_count_change++;
rd->m_requested_deadline_missed_status.last_instance_handle = data->handle;
metrics = (void*)&(rd->m_requested_deadline_missed_status);
break;
}
case DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS: {
rd->m_requested_incompatible_qos_status.total_count++;
rd->m_requested_incompatible_qos_status.total_count_change++;
rd->m_requested_incompatible_qos_status.last_policy_id = data->extra;
metrics = (void*)&(rd->m_requested_incompatible_qos_status);
break;
}
case DDS_SAMPLE_LOST_STATUS: {
rd->m_sample_lost_status.total_count++;
rd->m_sample_lost_status.total_count_change++;
metrics = (void*)&(rd->m_sample_lost_status);
break;
}
case DDS_SAMPLE_REJECTED_STATUS: {
rd->m_sample_rejected_status.total_count++;
rd->m_sample_rejected_status.total_count_change++;
rd->m_sample_rejected_status.last_reason = data->extra;
rd->m_sample_rejected_status.last_instance_handle = data->handle;
metrics = (void*)&(rd->m_sample_rejected_status);
break;
}
case DDS_DATA_AVAILABLE_STATUS: {
metrics = NULL;
break;
}
case DDS_LIVELINESS_CHANGED_STATUS: {
if (data->add) {
rd->m_liveliness_changed_status.alive_count++;
rd->m_liveliness_changed_status.alive_count_change++;
if (rd->m_liveliness_changed_status.not_alive_count > 0) {
rd->m_liveliness_changed_status.not_alive_count--;
}
} else {
rd->m_liveliness_changed_status.alive_count--;
rd->m_liveliness_changed_status.not_alive_count++;
rd->m_liveliness_changed_status.not_alive_count_change++;
}
rd->m_liveliness_changed_status.last_publication_handle = data->handle;
metrics = (void*)&(rd->m_liveliness_changed_status);
break;
}
case DDS_SUBSCRIPTION_MATCHED_STATUS: {
if (data->add) {
rd->m_subscription_matched_status.total_count++;
rd->m_subscription_matched_status.total_count_change++;
rd->m_subscription_matched_status.current_count++;
rd->m_subscription_matched_status.current_count_change++;
} else {
rd->m_subscription_matched_status.current_count--;
rd->m_subscription_matched_status.current_count_change--;
}
rd->m_subscription_matched_status.last_publication_handle = data->handle;
metrics = (void*)&(rd->m_subscription_matched_status);
break;
}
default: assert (0);
}
/* The reader needs to be unlocked when propagating the (possible) listener
* call because the application should be able to call this reader within
* the callback function. */
dds_reader_unlock(rd);
/* DATA_AVAILABLE is handled differently to normal status changes. */
if (data->status == DDS_DATA_AVAILABLE_STATUS) {
dds_entity *parent = rd->m_entity.m_parent;
/* First, try to ship it off to its parent(s) DDS_DATA_ON_READERS_STATUS. */
rc = dds_entity_listener_propagation(parent, parent, DDS_DATA_ON_READERS_STATUS, NULL, true);
if (rc == DDS_RETCODE_NO_DATA) {
/* No parent was interested (NO_DATA == NO_CALL).
* What about myself with DDS_DATA_AVAILABLE_STATUS? */
rc = dds_entity_listener_propagation(entity, entity, DDS_DATA_AVAILABLE_STATUS, NULL, false);
}
if ( rc == DDS_RETCODE_NO_DATA ) {
/* Nobody was interested (NO_DATA == NO_CALL). Set the status on the subscriber. */
dds_entity_status_set(parent, DDS_DATA_ON_READERS_STATUS);
/* Notify possible interested observers of the subscriber. */
dds_entity_status_signal(parent);
}
} else {
/* Is anybody interested within the entity hierarchy through listeners? */
rc = dds_entity_listener_propagation(entity, entity, data->status, metrics, true);
}
if (rc == DDS_RETCODE_OK) {
/* Event was eaten by a listener. */
if (dds_reader_lock(((dds_entity*)entity)->m_hdl, &rd) == DDS_RETCODE_OK) {
assert(rd == entity);
/* Reset the change counts of the metrics. */
switch (data->status) {
case DDS_REQUESTED_DEADLINE_MISSED_STATUS: {
rd->m_requested_deadline_missed_status.total_count_change = 0;
break;
}
case DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS: {
rd->m_requested_incompatible_qos_status.total_count_change = 0;
break;
}
case DDS_SAMPLE_LOST_STATUS: {
rd->m_sample_lost_status.total_count_change = 0;
break;
}
case DDS_SAMPLE_REJECTED_STATUS: {
rd->m_sample_rejected_status.total_count_change = 0;
break;
}
case DDS_DATA_AVAILABLE_STATUS: {
/* Nothing to reset. */;
break;
}
case DDS_LIVELINESS_CHANGED_STATUS: {
rd->m_liveliness_changed_status.alive_count_change = 0;
rd->m_liveliness_changed_status.not_alive_count_change = 0;
break;
}
case DDS_SUBSCRIPTION_MATCHED_STATUS: {
rd->m_subscription_matched_status.total_count_change = 0;
rd->m_subscription_matched_status.current_count_change = 0;
break;
}
default: assert (0);
}
dds_reader_unlock(rd);
} else {
/* There's a deletion or closing going on. */
}
} else if (rc == DDS_RETCODE_NO_DATA) {
/* Nobody was interested through a listener (NO_DATA == NO_CALL): set the status. */
dds_entity_status_set(entity, data->status);
/* Notify possible interested observers. */
dds_entity_status_signal(entity);
rc = DDS_RETCODE_OK;
} else if (rc == DDS_RETCODE_ALREADY_DELETED) {
/* An entity up the hierarchy is being deleted. */
rc = DDS_RETCODE_OK;
} else {
/* Something went wrong up the hierarchy. */
}
DDS_REPORT_FLUSH(rc != DDS_RETCODE_OK);
}
_Pre_satisfies_(((participant_or_subscriber & DDS_ENTITY_KIND_MASK) == DDS_KIND_SUBSCRIBER ) ||\
((participant_or_subscriber & DDS_ENTITY_KIND_MASK) == DDS_KIND_PARTICIPANT) )
_Pre_satisfies_(((topic & DDS_ENTITY_KIND_MASK) == DDS_KIND_TOPIC ) ||\
((topic & DDS_ENTITY_KIND_MASK) == DDS_KIND_INTERNAL) )
dds_entity_t
dds_create_reader(
_In_ dds_entity_t participant_or_subscriber,
_In_ dds_entity_t topic,
_In_opt_ const dds_qos_t *qos,
_In_opt_ const dds_listener_t *listener)
{
dds_qos_t * rqos;
dds__retcode_t rc;
dds_entity * sub = NULL;
dds_entity_t subscriber;
dds_reader * rd;
struct rhc * rhc;
dds_entity * tp;
dds_entity_t reader;
dds_entity_t t;
struct thread_state1 * const thr = lookup_thread_state ();
const bool asleep = !vtime_awake_p (thr->vtime);
dds_return_t ret = DDS_RETCODE_OK;
DDS_REPORT_STACK();
if (dds_entity_kind(topic) != DDS_KIND_INTERNAL) {
/* Try claiming a participant. If that's not working, then it could be a subscriber. */
if (dds_entity_kind(participant_or_subscriber) == DDS_KIND_PARTICIPANT) {
subscriber = dds_create_subscriber(participant_or_subscriber, qos, NULL);
} else {
subscriber = participant_or_subscriber;
}
t = topic;
} else {
/* TODO If qos is provided, we need to compare with writer qos to determine compatibility */
subscriber = dds__get_builtin_subscriber(participant_or_subscriber);
t = dds__get_builtin_topic(subscriber, topic);
}
rc = dds_entity_lock(subscriber, DDS_KIND_SUBSCRIBER, &sub);
if (rc != DDS_RETCODE_OK) {
reader = DDS_ERRNO(rc, "Error occurred on locking subscriber");
goto err_sub_lock;
}
if ((subscriber != participant_or_subscriber) &&
(dds_entity_kind(topic) != DDS_KIND_INTERNAL)) {
/* Delete implicit subscriber if reader creation fails */
sub->m_flags |= DDS_ENTITY_IMPLICIT;
}
rc = dds_entity_lock(t, DDS_KIND_TOPIC, &tp);
if (rc != DDS_RETCODE_OK) {
reader = DDS_ERRNO(rc, "Error occurred on locking topic");
goto err_tp_lock;
}
assert (((dds_topic*)tp)->m_stopic);
assert (sub->m_domain == tp->m_domain);
/* Merge qos from topic and subscriber */
rqos = dds_qos_create ();
if (qos) {
/* Only returns failure when one of the qos args is NULL, which
* is not the case here. */
(void)dds_qos_copy(rqos, qos);
}
if(sub->m_qos){
dds_qos_merge (rqos, sub->m_qos);
}
if (tp->m_qos) {
dds_qos_merge (rqos, tp->m_qos);
/* reset the following qos policies if set during topic qos merge as they aren't applicable for reader */
rqos->present &= ~(QP_DURABILITY_SERVICE | QP_TRANSPORT_PRIORITY | QP_LIFESPAN);
}
nn_xqos_mergein_missing (rqos, &gv.default_xqos_rd);
ret = dds_reader_qos_validate (rqos, false);
if (ret != 0) {
dds_qos_delete(rqos);
reader = ret;
goto err_bad_qos;
}
/* Create reader and associated read cache */
rd = dds_alloc (sizeof (*rd));
reader = dds_entity_init (&rd->m_entity, sub, DDS_KIND_READER, rqos, listener, DDS_READER_STATUS_MASK);
rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED;
rd->m_topic = (dds_topic*)tp;
rhc = dds_rhc_new (rd, ((dds_topic*)tp)->m_stopic);
dds_entity_add_ref_nolock (tp);
rd->m_entity.m_deriver.close = dds_reader_close;
rd->m_entity.m_deriver.delete = dds_reader_delete;
rd->m_entity.m_deriver.set_qos = dds_reader_qos_set;
rd->m_entity.m_deriver.validate_status = dds_reader_status_validate;
rd->m_entity.m_deriver.get_instance_hdl = dds_reader_instance_hdl;
/* Extra claim of this reader to make sure that the delete waits until DDSI
* has deleted its reader as well. This can be known through the callback. */
if (ut_handle_claim(rd->m_entity.m_hdl, rd->m_entity.m_hdllink, DDS_KIND_READER, NULL) != UT_HANDLE_OK) {
assert(0);
}
os_mutexUnlock(&tp->m_mutex);
os_mutexUnlock(&sub->m_mutex);
if (asleep) {
thread_state_awake (thr);
}
rd->m_rd = new_reader(&rd->m_entity.m_guid, NULL, &sub->m_participant->m_guid, ((dds_topic*)tp)->m_stopic,
rqos, rhc, dds_reader_status_cb, rd);
os_mutexLock(&sub->m_mutex);
os_mutexLock(&tp->m_mutex);
assert (rd->m_rd);
if (asleep) {
thread_state_asleep (thr);
}
/* For persistent data register reader with durability */
if (dds_global.m_dur_reader && (rd->m_entity.m_qos->durability.kind > NN_TRANSIENT_LOCAL_DURABILITY_QOS)) {
(dds_global.m_dur_reader) (rd, rhc);
}
dds_entity_unlock(tp);
dds_entity_unlock(sub);
if (dds_entity_kind(topic) == DDS_KIND_INTERNAL) {
/* If topic is builtin, then the topic entity is local and should
* be deleted because the application won't. */
dds_delete(t);
}
DDS_REPORT_FLUSH(reader <= 0);
return reader;
err_bad_qos:
dds_entity_unlock(tp);
err_tp_lock:
dds_entity_unlock(sub);
if((sub->m_flags & DDS_ENTITY_IMPLICIT) != 0){
(void)dds_delete(subscriber);
}
err_sub_lock:
DDS_REPORT_FLUSH(reader <= 0);
return reader;
}
void
dds_reader_ddsi2direct(
dds_entity_t entity,
ddsi2direct_directread_cb_t cb,
void *cbarg)
{
dds_reader *dds_rd;
if (ut_handle_claim(entity, NULL, DDS_KIND_READER, (void**)&dds_rd) == UT_HANDLE_OK)
{
struct reader *rd = dds_rd->m_rd;
nn_guid_t pwrguid;
struct proxy_writer *pwr;
struct rd_pwr_match *m;
memset (&pwrguid, 0, sizeof (pwrguid));
os_mutexLock (&rd->e.lock);
rd->ddsi2direct_cb = cb;
rd->ddsi2direct_cbarg = cbarg;
while ((m = ut_avlLookupSuccEq (&rd_writers_treedef, &rd->writers, &pwrguid)) != NULL)
{
/* have to be careful walking the tree -- pretty is different, but
I want to check this before I write a lookup_succ function. */
struct rd_pwr_match *m_next;
nn_guid_t pwrguid_next;
pwrguid = m->pwr_guid;
if ((m_next = ut_avlFindSucc (&rd_writers_treedef, &rd->writers, m)) != NULL)
pwrguid_next = m_next->pwr_guid;
else
{
memset (&pwrguid_next, 0xff, sizeof (pwrguid_next));
pwrguid_next.entityid.u = (pwrguid_next.entityid.u & ~0xff) | NN_ENTITYID_KIND_WRITER_NO_KEY;
}
os_mutexUnlock (&rd->e.lock);
if ((pwr = ephash_lookup_proxy_writer_guid (&pwrguid)) != NULL)
{
os_mutexLock (&pwr->e.lock);
pwr->ddsi2direct_cb = cb;
pwr->ddsi2direct_cbarg = cbarg;
os_mutexUnlock (&pwr->e.lock);
}
pwrguid = pwrguid_next;
os_mutexLock (&rd->e.lock);
}
os_mutexUnlock (&rd->e.lock);
ut_handle_release(entity, ((dds_entity*)rd)->m_hdllink);
}
}
uint32_t
dds_reader_lock_samples(
dds_entity_t reader)
{
uint32_t ret = 0;
dds_reader *rd;
ret = dds_reader_lock(reader, &rd);
if (ret == DDS_RETCODE_OK) {
ret = dds_rhc_lock_samples(rd->m_rd->rhc);
dds_reader_unlock(rd);
} else {
ret = 0;
}
return ret;
}
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER)
int
dds_reader_wait_for_historical_data(
dds_entity_t reader,
dds_duration_t max_wait)
{
int ret;
dds_reader *rd;
DDS_REPORT_STACK();
assert (reader);
ret = dds_reader_lock(reader, &rd);
if (ret == DDS_RETCODE_OK) {
if (((dds_entity*)rd)->m_qos->durability.kind > NN_TRANSIENT_LOCAL_DURABILITY_QOS) {
ret = (dds_global.m_dur_wait) (rd, max_wait);
} else {
ret = DDS_ERRNO(DDS_RETCODE_ERROR, "Can not wait for historical data on a reader with volatile durability");
}
dds_reader_unlock(rd);
} else {
ret = DDS_ERRNO(ret, "Error occurred on locking reader");
}
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_(((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER ) || \
((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_READ ) || \
((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_COND_QUERY) )
dds_entity_t
dds_get_subscriber(
_In_ dds_entity_t entity)
{
dds_entity_t hdl;
DDS_REPORT_STACK();
if (dds_entity_kind(entity) == DDS_KIND_READER) {
hdl = dds_get_parent(entity);
} else if (dds_entity_kind(entity) == DDS_KIND_COND_READ || dds_entity_kind(entity) == DDS_KIND_COND_QUERY) {
hdl = dds_get_parent(entity);
if(hdl > 0){
hdl = dds_get_subscriber(hdl);
} else {
DDS_ERROR(hdl, "Reader of this condition is already deleted");
}
} else {
hdl = DDS_ERRNO(dds_valid_hdl(entity, DDS_KIND_READER), "Provided entity is not a reader nor a condition");
}
DDS_REPORT_FLUSH(hdl <= 0);
return hdl;
}
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER)
dds_return_t
dds_get_subscription_matched_status (
_In_ dds_entity_t reader,
_Out_opt_ dds_subscription_matched_status_t * status)
{
dds__retcode_t rc;
dds_reader *rd;
dds_return_t ret = DDS_RETCODE_OK;
DDS_REPORT_STACK();
rc = dds_reader_lock(reader, &rd);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking reader");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = rd->m_subscription_matched_status;
}
if (((dds_entity*)rd)->m_status_enable & DDS_SUBSCRIPTION_MATCHED_STATUS) {
rd->m_subscription_matched_status.total_count_change = 0;
rd->m_subscription_matched_status.current_count_change = 0;
dds_entity_status_reset(rd, DDS_SUBSCRIPTION_MATCHED_STATUS);
}
dds_reader_unlock(rd);
fail:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER)
dds_return_t
dds_get_liveliness_changed_status (
_In_ dds_entity_t reader,
_Out_opt_ dds_liveliness_changed_status_t * status)
{
dds__retcode_t rc;
dds_reader *rd;
dds_return_t ret = DDS_RETCODE_OK;
DDS_REPORT_STACK();
rc = dds_reader_lock(reader, &rd);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking reader");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = rd->m_liveliness_changed_status;
}
if (((dds_entity*)rd)->m_status_enable & DDS_LIVELINESS_CHANGED_STATUS) {
rd->m_liveliness_changed_status.alive_count_change = 0;
rd->m_liveliness_changed_status.not_alive_count_change = 0;
dds_entity_status_reset(rd, DDS_LIVELINESS_CHANGED_STATUS);
}
dds_reader_unlock(rd);
fail:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER)
dds_return_t dds_get_sample_rejected_status (
_In_ dds_entity_t reader,
_Out_opt_ dds_sample_rejected_status_t * status)
{
dds__retcode_t rc;
dds_reader *rd;
dds_return_t ret = DDS_RETCODE_OK;
DDS_REPORT_STACK();
rc = dds_reader_lock(reader, &rd);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking reader");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = rd->m_sample_rejected_status;
}
if (((dds_entity*)rd)->m_status_enable & DDS_SAMPLE_REJECTED_STATUS) {
rd->m_sample_rejected_status.total_count_change = 0;
rd->m_sample_rejected_status.last_reason = DDS_NOT_REJECTED;
dds_entity_status_reset(rd, DDS_SAMPLE_REJECTED_STATUS);
}
dds_reader_unlock(rd);
fail:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER)
dds_return_t dds_get_sample_lost_status (
_In_ dds_entity_t reader,
_Out_opt_ dds_sample_lost_status_t * status)
{
dds__retcode_t rc;
dds_reader *rd;
dds_return_t ret = DDS_RETCODE_OK;
DDS_REPORT_STACK();
rc = dds_reader_lock(reader, &rd);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking reader");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = rd->m_sample_lost_status;
}
if (((dds_entity*)rd)->m_status_enable & DDS_SAMPLE_LOST_STATUS) {
rd->m_sample_lost_status.total_count_change = 0;
dds_entity_status_reset(rd, DDS_SAMPLE_LOST_STATUS);
}
dds_reader_unlock(rd);
fail:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER)
dds_return_t dds_get_requested_deadline_missed_status (
_In_ dds_entity_t reader,
_Out_opt_ dds_requested_deadline_missed_status_t * status)
{
dds__retcode_t rc;
dds_reader *rd;
dds_return_t ret = DDS_RETCODE_OK;
DDS_REPORT_STACK();
rc = dds_reader_lock(reader, &rd);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking reader");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = rd->m_requested_deadline_missed_status;
}
if (((dds_entity*)rd)->m_status_enable & DDS_REQUESTED_DEADLINE_MISSED_STATUS) {
rd->m_requested_deadline_missed_status.total_count_change = 0;
dds_entity_status_reset(rd, DDS_REQUESTED_DEADLINE_MISSED_STATUS);
}
dds_reader_unlock(rd);
fail:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_((reader & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER)
dds_return_t dds_get_requested_incompatible_qos_status (
_In_ dds_entity_t reader,
_Out_opt_ dds_requested_incompatible_qos_status_t * status)
{
dds__retcode_t rc;
dds_reader *rd;
dds_return_t ret = DDS_RETCODE_OK;
DDS_REPORT_STACK();
rc = dds_reader_lock(reader, &rd);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking reader");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = rd->m_requested_incompatible_qos_status;
}
if (((dds_entity*)rd)->m_status_enable & DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS) {
rd->m_requested_incompatible_qos_status.total_count_change = 0;
dds_entity_status_reset(rd, DDS_REQUESTED_INCOMPATIBLE_QOS_STATUS);
}
dds_reader_unlock(rd);
fail:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}

View file

@ -0,0 +1,53 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "ddsc/dds.h"
#include "os/os.h"
#include "os/os_report.h"
#include <assert.h>
#include <string.h>
#include "dds__report.h"
void
dds_report(
os_reportType reportType,
const char *function,
int32_t line,
const char *file,
dds_return_t code,
const char *format,
...)
{
const char *retcode = NULL;
/* os_report truncates messages to <OS_REPORT_BUFLEN> bytes */
char buffer[OS_REPORT_BUFLEN];
size_t offset = 0;
va_list args;
assert (function != NULL);
assert (file != NULL);
assert (format != NULL);
/* probably never happens, but you can never be to sure */
assert (OS_REPORT_BUFLEN > 0);
retcode = dds_err_str(code*-1);
offset = strlen(retcode);
assert (offset < OS_REPORT_BUFLEN);
(void)memcpy(buffer, retcode, offset);
buffer[offset] = ' ';
offset++;
va_start (args, format);
(void)os_vsnprintf (buffer + offset, sizeof(buffer) - offset, format, args);
va_end (args);
os_report (reportType, function, file, line, code, "%s", buffer);
}

2411
src/core/ddsc/src/dds_rhc.c Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,223 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <string.h>
#include "dds__listener.h"
#include "dds__qos.h"
#include "dds__err.h"
#include "ddsi/q_entity.h"
#include "dds__report.h"
#include "ddsc/ddsc_project.h"
#define DDS_SUBSCRIBER_STATUS_MASK \
DDS_DATA_ON_READERS_STATUS
static dds_return_t
dds_subscriber_instance_hdl(
dds_entity *e,
dds_instance_handle_t *i)
{
assert(e);
assert(i);
/* TODO: Get/generate proper handle. */
return DDS_ERRNO(DDS_RETCODE_UNSUPPORTED, "Generating subscriber instance handle is not supported");
}
static dds_return_t
dds__subscriber_qos_validate(
_In_ const dds_qos_t *qos,
_In_ bool enabled)
{
dds_return_t ret = DDS_RETCODE_OK;
assert(qos);
if((qos->present & QP_GROUP_DATA) && !validate_octetseq(&qos->group_data)) {
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Group data policy is inconsistent and caused an error");
}
if((qos->present & QP_PARTITION) && !validate_stringseq(&qos->partition)) {
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Partition policy is inconsistent and caused an error");
}
if((qos->present & QP_PRESENTATION) && validate_presentation_qospolicy(&qos->presentation)) {
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Presentation policy is inconsistent and caused an error");
}
if((qos->present & QP_PRISMTECH_ENTITY_FACTORY) && !validate_entityfactory_qospolicy(&qos->entity_factory)) {
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Prismtech entity factory policy is inconsistent and caused an error");
}
if(ret == DDS_RETCODE_OK && enabled && (qos->present & QP_PRESENTATION)) {
/* TODO: Improve/check immutable check. */
ret = DDS_ERRNO(DDS_RETCODE_IMMUTABLE_POLICY, "Presentation QoS policy is immutable");
}
return ret;
}
static dds_return_t
dds_subscriber_qos_set(
dds_entity *e,
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = dds__subscriber_qos_validate(qos, enabled);
if (ret == DDS_RETCODE_OK) {
if (enabled) {
/* TODO: CHAM-95: DDSI does not support changing QoS policies. */
ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED, DDSC_PROJECT_NAME" does not support changing QoS policies yet");
}
}
return ret;
}
static dds_return_t
dds_subscriber_status_validate(
uint32_t mask)
{
return (mask & ~(DDS_SUBSCRIBER_STATUS_MASK)) ?
DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Invalid status mask") :
DDS_RETCODE_OK;
}
/*
Set boolean on readers that indicates state of DATA_ON_READERS
status on parent subscriber
*/
static dds_return_t
dds_subscriber_status_propagate(
dds_entity *sub,
uint32_t mask,
bool set)
{
if (mask & DDS_DATA_ON_READERS_STATUS) {
dds_entity *iter = sub->m_children;
while (iter) {
os_mutexLock (&iter->m_mutex);
((dds_reader*) iter)->m_data_on_readers = set;
os_mutexUnlock (&iter->m_mutex);
iter = iter->m_next;
}
}
return DDS_RETCODE_OK;
}
_Requires_exclusive_lock_held_(participant)
_Check_return_ dds_entity_t
dds__create_subscriber_l(
_Inout_ dds_entity *participant, /* entity-lock must be held */
_In_opt_ const dds_qos_t *qos,
_In_opt_ const dds_listener_t *listener)
{
dds_subscriber * sub;
dds_entity_t subscriber;
dds_return_t ret;
dds_qos_t * new_qos;
/* Validate qos */
if (qos) {
if ((ret = dds__subscriber_qos_validate(qos, false)) != DDS_RETCODE_OK) {
goto err_param;
}
new_qos = dds_qos_create();
/* Only returns failure when one of the qos args is NULL, which
* is not the case here. */
(void)dds_qos_copy(new_qos, qos);
} else {
new_qos = NULL;
}
/* Create subscriber */
sub = dds_alloc(sizeof(*sub));
subscriber = dds_entity_init(&sub->m_entity, participant, DDS_KIND_SUBSCRIBER, new_qos, listener, DDS_SUBSCRIBER_STATUS_MASK);
sub->m_entity.m_deriver.set_qos = dds_subscriber_qos_set;
sub->m_entity.m_deriver.validate_status = dds_subscriber_status_validate;
sub->m_entity.m_deriver.propagate_status = dds_subscriber_status_propagate;
sub->m_entity.m_deriver.get_instance_hdl = dds_subscriber_instance_hdl;
return subscriber;
/* Error handling */
err_param:
return ret;
}
_Pre_satisfies_((participant & DDS_ENTITY_KIND_MASK) == DDS_KIND_PARTICIPANT)
_Must_inspect_result_ dds_entity_t
dds_create_subscriber(
_In_ dds_entity_t participant,
_In_opt_ const dds_qos_t *qos,
_In_opt_ const dds_listener_t *listener)
{
dds_entity * par;
dds_entity_t hdl;
dds__retcode_t errnr;
DDS_REPORT_STACK();
errnr = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par);
if (errnr != DDS_RETCODE_OK) {
hdl = DDS_ERRNO(errnr, "Error occurred on locking participant");
return hdl;
}
hdl = dds__create_subscriber_l(par, qos, listener);
dds_entity_unlock(par);
DDS_REPORT_FLUSH(hdl <= 0);
return hdl;
}
_Pre_satisfies_((subscriber & DDS_ENTITY_KIND_MASK) == DDS_KIND_SUBSCRIBER)
dds_return_t
dds_notify_readers(
_In_ dds_entity_t subscriber)
{
dds_entity *iter;
dds_entity *sub;
dds__retcode_t errnr;
dds_return_t ret;
DDS_REPORT_STACK();
errnr = dds_entity_lock(subscriber, DDS_KIND_SUBSCRIBER, &sub);
if (errnr == DDS_RETCODE_OK) {
errnr = DDS_RETCODE_UNSUPPORTED;
ret = DDS_ERRNO(errnr, "Unsupported operation");
iter = sub->m_children;
while (iter) {
os_mutexLock(&iter->m_mutex);
// TODO: check if reader has data available, call listener
os_mutexUnlock(&iter->m_mutex);
iter = iter->m_next;
}
dds_entity_unlock(sub);
} else {
ret = DDS_ERRNO(errnr, "Error occurred on locking subscriber");
}
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
dds_return_t
dds_subscriber_begin_coherent(
_In_ dds_entity_t e)
{
/* TODO: CHAM-124 Currently unsupported. */
return DDS_ERRNO(DDS_RETCODE_UNSUPPORTED, "Using coherency to get a coherent data set is not currently being supported");
}
dds_return_t
dds_subscriber_end_coherent(
_In_ dds_entity_t e)
{
/* TODO: CHAM-124 Currently unsupported. */
return DDS_ERRNO(DDS_RETCODE_UNSUPPORTED, "Using coherency to get a coherent data set is not currently being supported");
}

View file

@ -0,0 +1,41 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "ddsc/dds.h"
#include "os/os.h"
dds_time_t dds_time (void)
{
os_time time;
/* Get the current time */
time = os_timeGet ();
/* convert os_time to dds_time_t */
dds_time_t dds_time = time.tv_nsec + (time.tv_sec * DDS_NSECS_IN_SEC);
return dds_time;
}
void dds_sleepfor (dds_duration_t n)
{
os_time interval = { (os_timeSec) (n / DDS_NSECS_IN_SEC), (uint32_t) (n % DDS_NSECS_IN_SEC) };
os_nanoSleep (interval);
}
void dds_sleepuntil (dds_time_t n)
{
dds_time_t interval = n - dds_time ();
if (interval > 0)
{
dds_sleepfor (interval);
}
}

View file

@ -0,0 +1,393 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include "ddsi/q_thread.h"
#include "ddsi/q_unused.h"
#include "ddsi/q_gc.h"
#include "ddsi/q_globals.h"
#include "ddsi/q_config.h"
#include "ddsi/sysdeps.h"
#include "dds__tkmap.h"
#include "dds__iid.h"
#include "util/ut_hopscotch.h"
#include "dds__stream.h"
#include "os/os.h"
#include "q__osplser.h"
#define REFC_DELETE 0x80000000
#define REFC_MASK 0x0fffffff
struct tkmap
{
struct ut_chh * m_hh;
os_mutex m_lock;
os_cond m_cond;
};
static void gc_buckets_impl (struct gcreq *gcreq)
{
os_free (gcreq->arg);
gcreq_free (gcreq);
}
static void gc_buckets (void *a)
{
struct gcreq *gcreq = gcreq_new (gv.gcreq_queue, gc_buckets_impl);
gcreq->arg = a;
gcreq_enqueue (gcreq);
}
static void gc_tkmap_instance_impl (struct gcreq *gcreq)
{
struct tkmap_instance *tk = gcreq->arg;
ddsi_serdata_unref (tk->m_sample);
dds_free (tk);
gcreq_free (gcreq);
}
static void gc_tkmap_instance (struct tkmap_instance *tk)
{
struct gcreq *gcreq = gcreq_new (gv.gcreq_queue, gc_tkmap_instance_impl);
gcreq->arg = tk;
gcreq_enqueue (gcreq);
}
/* Fixed seed and length */
#define DDS_MH3_LEN 16
#define DDS_MH3_SEED 0
#define DDS_MH3_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
/* Really
http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp,
MurmurHash3_x86_32
*/
static uint32_t dds_mh3 (const void * key)
{
const uint8_t *data = (const uint8_t *) key;
const intptr_t nblocks = (intptr_t) (DDS_MH3_LEN / 4);
const uint32_t c1 = 0xcc9e2d51;
const uint32_t c2 = 0x1b873593;
uint32_t h1 = DDS_MH3_SEED;
const uint32_t *blocks = (const uint32_t *) (data + nblocks * 4);
register intptr_t i;
for (i = -nblocks; i; i++)
{
uint32_t k1 = blocks[i];
k1 *= c1;
k1 = DDS_MH3_ROTL32 (k1, 15);
k1 *= c2;
h1 ^= k1;
h1 = DDS_MH3_ROTL32 (h1, 13);
h1 = h1 * 5+0xe6546b64;
}
/* finalization */
h1 ^= DDS_MH3_LEN;
h1 ^= h1 >> 16;
h1 *= 0x85ebca6b;
h1 ^= h1 >> 13;
h1 *= 0xc2b2ae35;
h1 ^= h1 >> 16;
return h1;
}
static uint32_t dds_tk_hash (const struct tkmap_instance * inst)
{
volatile struct serdata * sd = (volatile struct serdata *) inst->m_sample;
if (! sd->v.hash_valid)
{
const uint32_t * k = (const uint32_t *) sd->v.keyhash.m_hash;
const uint32_t hash0 = sd->v.st->topic ? sd->v.st->topic->hash : 0;
sd->v.hash = ((sd->v.keyhash.m_flags & DDS_KEY_IS_HASH) ? dds_mh3 (k) : (*k)) ^ hash0;
sd->v.hash_valid = 1;
}
return sd->v.hash;
}
static uint32_t dds_tk_hash_void (const void * inst)
{
return dds_tk_hash (inst);
}
static int dds_tk_equals (const struct tkmap_instance *a, const struct tkmap_instance *b)
{
return serdata_cmp (a->m_sample, b->m_sample) == 0;
}
static int dds_tk_equals_void (const void *a, const void *b)
{
return dds_tk_equals (a, b);
}
struct tkmap * dds_tkmap_new (void)
{
struct tkmap *tkmap = dds_alloc (sizeof (*tkmap));
tkmap->m_hh = ut_chhNew (1, dds_tk_hash_void, dds_tk_equals_void, gc_buckets);
os_mutexInit (&tkmap->m_lock);
os_condInit (&tkmap->m_cond, &tkmap->m_lock);
return tkmap;
}
static void free_tkmap_instance (void *vtk, UNUSED_ARG(void *f_arg))
{
struct tkmap_instance *tk = vtk;
ddsi_serdata_unref (tk->m_sample);
os_free (tk);
}
void dds_tkmap_free (_Inout_ _Post_invalid_ struct tkmap * map)
{
ut_chhEnumUnsafe (map->m_hh, free_tkmap_instance, NULL);
ut_chhFree (map->m_hh);
os_condDestroy (&map->m_cond);
os_mutexDestroy (&map->m_lock);
dds_free (map);
}
uint64_t dds_tkmap_lookup (_In_ struct tkmap * map, _In_ const struct serdata * sd)
{
struct tkmap_instance dummy;
struct tkmap_instance * tk;
dummy.m_sample = (struct serdata *) sd;
tk = ut_chhLookup (map->m_hh, &dummy);
return (tk) ? tk->m_iid : DDS_HANDLE_NIL;
}
typedef struct
{
uint64_t m_iid;
void * m_sample;
bool m_ret;
}
tkmap_get_key_arg;
static void dds_tkmap_get_key_fn (void * vtk, void * varg)
{
struct tkmap_instance * tk = vtk;
tkmap_get_key_arg * arg = (tkmap_get_key_arg*) varg;
if (tk->m_iid == arg->m_iid)
{
deserialize_into (arg->m_sample, tk->m_sample);
arg->m_ret = true;
}
}
_Check_return_
bool dds_tkmap_get_key (_In_ struct tkmap * map, _In_ uint64_t iid, _Out_ void * sample)
{
tkmap_get_key_arg arg = { iid, sample, false };
os_mutexLock (&map->m_lock);
ut_chhEnumUnsafe (map->m_hh, dds_tkmap_get_key_fn, &arg);
os_mutexUnlock (&map->m_lock);
return arg.m_ret;
}
typedef struct
{
uint64_t m_iid;
struct tkmap_instance * m_inst;
}
tkmap_get_inst_arg;
static void dds_tkmap_get_inst_fn (void * vtk, void * varg)
{
struct tkmap_instance * tk = vtk;
tkmap_get_inst_arg * arg = (tkmap_get_inst_arg*) varg;
if (tk->m_iid == arg->m_iid)
{
arg->m_inst = tk;
}
}
_Check_return_
struct tkmap_instance * dds_tkmap_find_by_id (_In_ struct tkmap * map, _In_ uint64_t iid)
{
tkmap_get_inst_arg arg = { iid, NULL };
ut_chhEnumUnsafe (map->m_hh, dds_tkmap_get_inst_fn, &arg);
return arg.m_inst;
}
/* Debug keyhash generation for debug and coverage builds */
#ifdef NDEBUG
#if VL_BUILD_LCOV
#define DDS_DEBUG_KEYHASH 1
#else
#define DDS_DEBUG_KEYHASH 0
#endif
#else
#define DDS_DEBUG_KEYHASH 1
#endif
_Check_return_
struct tkmap_instance * dds_tkmap_find(
_In_opt_ const struct dds_topic * topic,
_In_ struct serdata * sd,
_In_ const bool rd,
_In_ const bool create)
{
struct tkmap_instance dummy;
struct tkmap_instance * tk;
struct tkmap * map = gv.m_tkmap;
dummy.m_sample = sd;
/* Generate key hash if required and not provided */
if (topic && topic->m_descriptor->m_nkeys)
{
if ((sd->v.keyhash.m_flags & DDS_KEY_HASH_SET) == 0)
{
dds_stream_t is;
dds_stream_from_serstate (&is, sd->v.st);
dds_stream_read_keyhash (&is, &sd->v.keyhash, topic->m_descriptor, sd->v.st->kind == STK_KEY);
}
else
{
if (topic->m_descriptor->m_flagset & DDS_TOPIC_FIXED_KEY)
{
sd->v.keyhash.m_flags |= DDS_KEY_IS_HASH;
}
#if DDS_DEBUG_KEYHASH
{
dds_stream_t is;
dds_key_hash_t kh;
/* Check that we generate same keyhash as provided */
memset (&kh, 0, sizeof (kh));
dds_stream_from_serstate (&is, sd->v.st);
dds_stream_read_keyhash (&is, &kh, topic->m_descriptor, sd->v.st->kind == STK_KEY);
assert (memcmp (kh.m_hash, sd->v.keyhash.m_hash, 16) == 0);
if (kh.m_key_buff_size)
{
dds_free (kh.m_key_buff);
}
}
#endif
}
}
retry:
if ((tk = ut_chhLookup(map->m_hh, &dummy)) != NULL)
{
uint32_t new;
new = os_atomic_inc32_nv(&tk->m_refc);
if (new & REFC_DELETE)
{
/* for the unlikely case of spinning 2^31 times across all threads ... */
os_atomic_dec32(&tk->m_refc);
/* simplest action would be to just spin, but that can potentially take a long time;
we can block until someone signals some entry is removed from the map if we take
some lock & wait for some condition */
os_mutexLock(&map->m_lock);
while ((tk = ut_chhLookup(map->m_hh, &dummy)) != NULL && (os_atomic_ld32(&tk->m_refc) & REFC_DELETE))
os_condWait(&map->m_cond, &map->m_lock);
os_mutexUnlock(&map->m_lock);
goto retry;
}
}
else if (create)
{
if ((tk = dds_alloc (sizeof (*tk))) == NULL)
return NULL;
tk->m_sample = ddsi_serdata_ref (sd);
tk->m_map = map;
os_atomic_st32 (&tk->m_refc, 1);
tk->m_iid = dds_iid_gen ();
if (!ut_chhAdd (map->m_hh, tk))
{
/* Lost a race from another thread, retry */
ddsi_serdata_unref (tk->m_sample);
dds_free (tk);
goto retry;
}
}
if (tk && rd)
{
TRACE (("tk=%p iid=%"PRIx64"", &tk, tk->m_iid));
}
return tk;
}
_Check_return_
struct tkmap_instance * dds_tkmap_lookup_instance_ref (_In_ struct serdata * sd)
{
dds_topic * topic = sd->v.st->topic ? sd->v.st->topic->status_cb_entity : NULL;
assert (vtime_awake_p (lookup_thread_state ()->vtime));
#if 0
/* Topic might have been deleted -- FIXME: no way the topic may be deleted when there're still users out there */
if (topic == NULL)
{
return NULL;
}
#endif
return dds_tkmap_find (topic, sd, true, true);
}
void dds_tkmap_instance_ref (_In_ struct tkmap_instance *tk)
{
os_atomic_inc32 (&tk->m_refc);
}
void dds_tkmap_instance_unref (_In_ struct tkmap_instance * tk)
{
uint32_t old, new;
assert (vtime_awake_p(lookup_thread_state()->vtime));
do {
old = os_atomic_ld32(&tk->m_refc);
if (old == 1)
new = REFC_DELETE;
else
{
assert(!(old & REFC_DELETE));
new = old - 1;
}
} while (!os_atomic_cas32(&tk->m_refc, old, new));
if (new == REFC_DELETE)
{
struct tkmap *map = tk->m_map;
/* Remove from hash table */
(void)ut_chhRemove(map->m_hh, tk);
/* Signal any threads blocked in their retry loops in lookup */
os_mutexLock(&map->m_lock);
os_condBroadcast(&map->m_cond);
os_mutexUnlock(&map->m_lock);
/* Schedule freeing of memory until after all those who may have found a pointer have
progressed to where they no longer hold that pointer */
gc_tkmap_instance(tk);
}
}

View file

@ -0,0 +1,631 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include "dds__topic.h"
#include "dds__listener.h"
#include "dds__qos.h"
#include "dds__stream.h"
#include "dds__init.h"
#include "dds__domain.h"
#include "dds__err.h"
#include "ddsi/q_entity.h"
#include "ddsi/q_thread.h"
#include "q__osplser.h"
#include "ddsi/q_ddsi_discovery.h"
#include "os/os_atomics.h"
#include "dds__report.h"
#define DDS_TOPIC_STATUS_MASK \
DDS_INCONSISTENT_TOPIC_STATUS
const ut_avlTreedef_t dds_topictree_def = UT_AVL_TREEDEF_INITIALIZER_INDKEY
(
offsetof (struct sertopic, avlnode),
offsetof (struct sertopic, name_typename),
(int (*) (const void *, const void *)) strcmp,
0
);
/* builtin-topic handles */
const dds_entity_t DDS_BUILTIN_TOPIC_DCPSPARTICIPANT = (DDS_KIND_INTERNAL + 1);
const dds_entity_t DDS_BUILTIN_TOPIC_CMPARTICIPANT = (DDS_KIND_INTERNAL + 2);
const dds_entity_t DDS_BUILTIN_TOPIC_DCPSTYPE = (DDS_KIND_INTERNAL + 3);
const dds_entity_t DDS_BUILTIN_TOPIC_DCPSTOPIC = (DDS_KIND_INTERNAL + 4);
const dds_entity_t DDS_BUILTIN_TOPIC_DCPSPUBLICATION = (DDS_KIND_INTERNAL + 5);
const dds_entity_t DDS_BUILTIN_TOPIC_CMPUBLISHER = (DDS_KIND_INTERNAL + 6);
const dds_entity_t DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION = (DDS_KIND_INTERNAL + 7);
const dds_entity_t DDS_BUILTIN_TOPIC_CMSUBSCRIBER = (DDS_KIND_INTERNAL + 8);
const dds_entity_t DDS_BUILTIN_TOPIC_CMDATAWRITER = (DDS_KIND_INTERNAL + 9);
const dds_entity_t DDS_BUILTIN_TOPIC_CMDATAREADER = (DDS_KIND_INTERNAL + 10);
static bool
is_valid_name(
_In_ const char *name)
{
bool valid = false;
/* DDS Spec:
* | TOPICNAME - A topic name is an identifier for a topic, and is defined as any series of characters
* | 'a', ..., 'z',
* | 'A', ..., 'Z',
* | '0', ..., '9',
* | '-' but may not start with a digit.
* It is considered that '-' is an error in the spec and should say '_'. So, that's what we'll check for.
*/
assert(name);
if ((name[0] != '\0') && (!isdigit((unsigned char)name[0]))) {
while (isalnum((unsigned char)*name) || (*name == '_')) {
name++;
}
if (*name == '\0') {
valid = true;
}
}
return valid;
}
static dds_return_t
dds_topic_status_validate(
uint32_t mask)
{
return (mask & ~(DDS_TOPIC_STATUS_MASK)) ?
DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument mask is invalid") :
DDS_RETCODE_OK;
}
/*
Topic status change callback handler. Supports INCONSISTENT_TOPIC
status (only defined status on a topic).
*/
static void
dds_topic_status_cb(
struct dds_topic *cb_t)
{
dds_topic *topic;
dds__retcode_t rc;
void *metrics = NULL;
DDS_REPORT_STACK();
if (dds_topic_lock(((dds_entity*)cb_t)->m_hdl, &topic) != DDS_RETCODE_OK) {
/* There's a deletion or closing going on. */
DDS_REPORT_FLUSH(false);
return;
}
assert(topic == cb_t);
/* Reset the status for possible Listener call.
* When a listener is not called, the status will be set (again). */
/* Update status metrics. */
topic->m_inconsistent_topic_status.total_count++;
topic->m_inconsistent_topic_status.total_count_change++;
/* The topic needs to be unlocked when propagating the (possible) listener
* call because the application should be able to call this topic within
* the callback function. */
dds_topic_unlock(topic);
/* Is anybody interested within the entity hierarchy through listeners? */
rc = dds_entity_listener_propagation((dds_entity*)topic,
(dds_entity*)topic,
DDS_INCONSISTENT_TOPIC_STATUS,
(void*)&(topic->m_inconsistent_topic_status),
true);
if (rc == DDS_RETCODE_OK) {
/* Event was eaten by a listener. */
if (dds_topic_lock(((dds_entity*)cb_t)->m_hdl, &topic) == DDS_RETCODE_OK) {
/* Reset the change counts of the metrics. */
topic->m_inconsistent_topic_status.total_count_change = 0;
dds_topic_unlock(topic);
}
} else if (rc == DDS_RETCODE_NO_DATA) {
/* Nobody was interested through a listener (NO_DATA == NO_CALL): set the status. */
dds_entity_status_set((dds_entity*)topic, DDS_INCONSISTENT_TOPIC_STATUS);
/* Notify possible interested observers. */
dds_entity_status_signal((dds_entity*)topic);
rc = DDS_RETCODE_OK;
} else if (rc == DDS_RETCODE_ALREADY_DELETED) {
/* An entity up the hierarchy is being deleted. */
rc = DDS_RETCODE_OK;
} else {
/* Something went wrong up the hierarchy. */
}
DDS_REPORT_FLUSH(rc != DDS_RETCODE_OK);
}
sertopic_t
dds_topic_lookup(
dds_domain *domain,
const char *name)
{
sertopic_t st = NULL;
ut_avlIter_t iter;
assert (domain);
assert (name);
os_mutexLock (&dds_global.m_mutex);
st = ut_avlIterFirst (&dds_topictree_def, &domain->m_topics, &iter);
while (st) {
if (strcmp (st->name, name) == 0) {
break;
}
st = ut_avlIterNext (&iter);
}
os_mutexUnlock (&dds_global.m_mutex);
return st;
}
void
dds_topic_free(
dds_domainid_t domainid,
struct sertopic *st)
{
dds_domain *domain;
assert (st);
os_mutexLock (&dds_global.m_mutex);
domain = (dds_domain*) ut_avlLookup (&dds_domaintree_def, &dds_global.m_domains, &domainid);
if (domain != NULL) {
ut_avlDelete (&dds_topictree_def, &domain->m_topics, st);
}
os_mutexUnlock (&dds_global.m_mutex);
st->status_cb_entity = NULL;
sertopic_free (st);
}
static void
dds_topic_add(
dds_domainid_t id,
sertopic_t st)
{
dds_domain * dom;
os_mutexLock (&dds_global.m_mutex);
dom = dds_domain_find_locked (id);
assert (dom);
ut_avlInsert (&dds_topictree_def, &dom->m_topics, st);
os_mutexUnlock (&dds_global.m_mutex);
}
_Pre_satisfies_((participant & DDS_ENTITY_KIND_MASK) == DDS_KIND_PARTICIPANT)
DDS_EXPORT dds_entity_t
dds_find_topic(
_In_ dds_entity_t participant,
_In_z_ const char *name)
{
dds_entity_t tp;
dds_entity *p = NULL;
sertopic_t st;
dds__retcode_t rc;
DDS_REPORT_STACK();
if (name) {
rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &p);
if (rc == DDS_RETCODE_OK) {
st = dds_topic_lookup (p->m_domain, name);
if (st) {
dds_entity_add_ref (&st->status_cb_entity->m_entity);
tp = st->status_cb_entity->m_entity.m_hdl;
} else {
tp = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET, "Topic is not being created yet");
}
dds_entity_unlock(p);
} else {
tp = DDS_ERRNO(rc, "Error occurred on locking entity");
}
} else {
tp = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument name is not valid");
}
DDS_REPORT_FLUSH(tp <= 0);
return tp;
}
static dds_return_t
dds_topic_delete(
dds_entity *e)
{
dds_topic_free(e->m_domainid, ((dds_topic*) e)->m_stopic);
return DDS_RETCODE_OK;
}
static dds_return_t
dds_topic_qos_validate(
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = DDS_RETCODE_OK;
assert(qos);
/* Check consistency. */
if (!dds_qos_validate_common(qos)) {
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument QoS is not valid");
}
if ((qos->present & QP_GROUP_DATA) && !validate_octetseq (&qos->group_data)) {
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Group data QoS policy is inconsistent and caused an error");
}
if ((qos->present & QP_DURABILITY_SERVICE) && (validate_durability_service_qospolicy(&qos->durability_service) != 0)) {
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Durability service QoS policy is inconsistent and caused an error");
}
if ((qos->present & QP_LIFESPAN) && (validate_duration(&qos->lifespan.duration) != 0)) {
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Lifespan QoS policy is inconsistent and caused an error");
}
if (qos->present & QP_HISTORY && (qos->present & QP_RESOURCE_LIMITS) && (validate_history_and_resource_limits(&qos->history, &qos->resource_limits) != 0)) {
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Lifespan QoS policy is inconsistent and caused an error");
}
if(ret == DDS_RETCODE_OK && enabled){
ret = dds_qos_validate_mutable_common(qos);
}
return ret;
}
static dds_return_t
dds_topic_qos_set(
dds_entity *e,
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = dds_topic_qos_validate(qos, enabled);
if (ret == DDS_RETCODE_OK) {
if (enabled) {
/* TODO: CHAM-95: DDSI does not support changing QoS policies. */
ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED, "Changing the topic QoS is not supported.");
}
}
return ret;
}
_Pre_satisfies_((participant & DDS_ENTITY_KIND_MASK) == DDS_KIND_PARTICIPANT)
DDS_EXPORT dds_entity_t
dds_create_topic(
_In_ dds_entity_t participant,
_In_ const dds_topic_descriptor_t *desc,
_In_z_ const char *name,
_In_opt_ const dds_qos_t *qos,
_In_opt_ const dds_listener_t *listener)
{
static uint32_t next_topicid = 0;
char *key = NULL;
sertopic_t st;
const char *typename;
dds__retcode_t rc;
dds_entity *par;
dds_topic *top;
dds_qos_t *new_qos = NULL;
nn_plist_t plist;
dds_entity_t hdl;
struct participant *ddsi_pp;
struct thread_state1 *const thr = lookup_thread_state ();
const bool asleep = !vtime_awake_p (thr->vtime);
uint32_t index;
DDS_REPORT_STACK();
if (desc == NULL){
hdl = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Topic description is NULL");
goto bad_param_err;
}
if (name == NULL) {
hdl = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Topic name is NULL");
goto bad_param_err;
}
if (!is_valid_name(name)) {
hdl = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Topic name contains characters that are not allowed.");
goto bad_param_err;
}
rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par);
if (rc != DDS_RETCODE_OK) {
hdl = DDS_ERRNO(rc, "Error occurred on locking entity");
goto lock_err;
}
/* Validate qos */
if (qos) {
hdl = dds_topic_qos_validate (qos, false);
if (hdl != DDS_RETCODE_OK) {
goto qos_err;
}
}
/* Check if topic already exists with same name */
if (dds_topic_lookup (par->m_domain, name)) {
hdl = DDS_ERRNO(DDS_RETCODE_PRECONDITION_NOT_MET, "Precondition not met");
goto qos_err;
}
typename = desc->m_typename;
key = (char*) dds_alloc (strlen (name) + strlen (typename) + 2);
strcpy (key, name);
strcat (key, "/");
strcat (key, typename);
if (qos) {
new_qos = dds_qos_create();
/* Only returns failure when one of the qos args is NULL, which
* is not the case here. */
(void)dds_qos_copy(new_qos, qos);
}
/* Create topic */
top = dds_alloc (sizeof (*top));
top->m_descriptor = desc;
hdl = dds_entity_init (&top->m_entity, par, DDS_KIND_TOPIC, new_qos, listener, DDS_TOPIC_STATUS_MASK);
top->m_entity.m_deriver.delete = dds_topic_delete;
top->m_entity.m_deriver.set_qos = dds_topic_qos_set;
top->m_entity.m_deriver.validate_status = dds_topic_status_validate;
st = dds_alloc (sizeof (*st));
st->type = (void*) desc;
os_atomic_st32 (&st->refcount, 1);
st->status_cb = dds_topic_status_cb;
st->status_cb_entity = top;
st->name_typename = key;
st->name = dds_alloc (strlen (name) + 1);
strcpy (st->name, name);
st->typename = dds_alloc (strlen (typename) + 1);
strcpy (st->typename, typename);
st->nkeys = desc->m_nkeys;
st->keys = desc->m_keys;
st->id = next_topicid++;
#ifdef VXWORKS_RTP
st->hash = (st->id * UINT64_C (12844332200329132887UL)) >> 32;
#else
st->hash = (st->id * UINT64_C (12844332200329132887)) >> 32;
#endif
/* Check if topic cannot be optimised (memcpy marshal) */
if ((desc->m_flagset & DDS_TOPIC_NO_OPTIMIZE) == 0) {
st->opt_size = dds_stream_check_optimize (desc);
}
top->m_stopic = st;
/* Add topic to extent */
dds_topic_add (par->m_domainid, st);
nn_plist_init_empty (&plist);
if (new_qos) {
dds_qos_merge (&plist.qos, new_qos);
}
/* Set Topic meta data (for SEDP publication) */
plist.qos.topic_name = dds_string_dup (st->name);
plist.qos.type_name = dds_string_dup (st->typename);
plist.qos.present |= (QP_TOPIC_NAME | QP_TYPE_NAME);
if (desc->m_meta) {
plist.type_description = dds_string_dup (desc->m_meta);
plist.present |= PP_PRISMTECH_TYPE_DESCRIPTION;
}
if (desc->m_nkeys) {
plist.qos.present |= QP_PRISMTECH_SUBSCRIPTION_KEYS;
plist.qos.subscription_keys.use_key_list = 1;
plist.qos.subscription_keys.key_list.n = desc->m_nkeys;
plist.qos.subscription_keys.key_list.strs = dds_alloc (desc->m_nkeys * sizeof (char*));
for (index = 0; index < desc->m_nkeys; index++) {
plist.qos.subscription_keys.key_list.strs[index] = dds_string_dup (desc->m_keys[index].m_name);
}
}
/* Publish Topic */
if (asleep) {
thread_state_awake (thr);
}
ddsi_pp = ephash_lookup_participant_guid (&par->m_guid);
assert (ddsi_pp);
sedp_write_topic (ddsi_pp, &plist);
if (asleep) {
thread_state_asleep (thr);
}
nn_plist_fini (&plist);
qos_err:
dds_entity_unlock(par);
lock_err:
bad_param_err:
DDS_REPORT_FLUSH(hdl <= 0);
return hdl;
}
static bool
dds_topic_chaining_filter(
const void *sample,
void *ctx)
{
dds_topic_filter_fn realf = (dds_topic_filter_fn)ctx;
return realf (sample);
}
static void
dds_topic_mod_filter(
dds_entity_t topic,
dds_topic_intern_filter_fn *filter,
void **ctx,
bool set)
{
dds_topic *t;
if (dds_topic_lock(topic, &t) == DDS_RETCODE_OK) {
if (set) {
t->m_stopic->filter_fn = *filter;
t->m_stopic->filter_ctx = *ctx;
/* Create sample for read filtering */
if (t->m_stopic->filter_sample == NULL) {
t->m_stopic->filter_sample = dds_alloc (t->m_descriptor->m_size);
}
} else {
*filter = t->m_stopic->filter_fn;
*ctx = t->m_stopic->filter_ctx;
}
dds_topic_unlock(t);
}
}
_Pre_satisfies_((topic & DDS_ENTITY_KIND_MASK) == DDS_KIND_TOPIC)
void
dds_topic_set_filter(
dds_entity_t topic,
dds_topic_filter_fn filter)
{
dds_topic_intern_filter_fn chaining = dds_topic_chaining_filter;
void *realf = (void *)filter;
dds_topic_mod_filter (topic, &chaining, &realf, true);
}
_Pre_satisfies_((topic & DDS_ENTITY_KIND_MASK) == DDS_KIND_TOPIC)
dds_topic_filter_fn
dds_topic_get_filter(
dds_entity_t topic)
{
dds_topic_intern_filter_fn filter;
void *ctx;
dds_topic_mod_filter (topic, &filter, &ctx, false);
return
(filter == dds_topic_chaining_filter) ? (dds_topic_filter_fn)ctx : NULL;
}
void
dds_topic_set_filter_with_ctx(
dds_entity_t topic,
dds_topic_intern_filter_fn filter,
void *ctx)
{
dds_topic_mod_filter (topic, &filter, &ctx, true);
}
dds_topic_intern_filter_fn
dds_topic_get_filter_with_ctx(
dds_entity_t topic)
{
dds_topic_intern_filter_fn filter;
void *ctx;
dds_topic_mod_filter (topic, &filter, &ctx, false);
return (filter == dds_topic_chaining_filter) ? NULL : filter;
}
_Pre_satisfies_((topic & DDS_ENTITY_KIND_MASK) == DDS_KIND_TOPIC)
DDS_EXPORT dds_return_t
dds_get_name(
_In_ dds_entity_t topic,
_Out_writes_z_(size) char *name,
_In_ size_t size)
{
dds_topic *t;
dds_return_t ret;
dds__retcode_t rc;
DDS_REPORT_STACK();
if(size <= 0){
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument size is smaller than 0");
goto fail;
}
if(name == NULL){
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument name is NULL");
goto fail;
}
name[0] = '\0';
rc = dds_topic_lock(topic, &t);
if (rc == DDS_RETCODE_OK) {
(void)snprintf(name, size, "%s", t->m_stopic->name);
dds_topic_unlock(t);
ret = DDS_RETCODE_OK;
} else {
ret = DDS_ERRNO(rc, "Error occurred on locking topic");
goto fail;
}
fail:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_((topic & DDS_ENTITY_KIND_MASK) == DDS_KIND_TOPIC)
DDS_EXPORT dds_return_t
dds_get_type_name(
_In_ dds_entity_t topic,
_Out_writes_z_(size) char *name,
_In_ size_t size)
{
dds_topic *t;
dds__retcode_t rc;
dds_return_t ret;
DDS_REPORT_STACK();
if(size <= 0){
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument size is smaller than 0");
goto fail;
}
if(name == NULL){
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument name is NULL");
goto fail;
}
name[0] = '\0';
rc = dds_topic_lock(topic, &t);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking topic");
goto fail;
}
(void)snprintf(name, size, "%s", t->m_stopic->typename);
dds_topic_unlock(t);
ret = DDS_RETCODE_OK;
fail:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_((topic & DDS_ENTITY_KIND_MASK) == DDS_KIND_TOPIC)
dds_return_t
dds_get_inconsistent_topic_status(
_In_ dds_entity_t topic,
_Out_opt_ dds_inconsistent_topic_status_t *status)
{
dds__retcode_t rc;
dds_topic *t;
dds_return_t ret = DDS_RETCODE_OK;
DDS_REPORT_STACK();
rc = dds_topic_lock(topic, &t);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking topic");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = t->m_inconsistent_topic_status;
}
if (((dds_entity*)t)->m_status_enable & DDS_INCONSISTENT_TOPIC_STATUS) {
t->m_inconsistent_topic_status.total_count_change = 0;
dds_entity_status_reset(t, DDS_INCONSISTENT_TOPIC_STATUS);
}
dds_topic_unlock(t);
fail:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}

View file

@ -0,0 +1,512 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include "os/os.h"
#include "dds__entity.h"
#include "dds__querycond.h"
#include "dds__readcond.h"
#include "dds__rhc.h"
#include "dds__err.h"
#include "dds__report.h"
#define dds_waitset_lock(hdl, obj) dds_entity_lock(hdl, DDS_KIND_WAITSET, (dds_entity**)obj)
#define dds_waitset_unlock(obj) dds_entity_unlock((dds_entity*)obj);
static void
dds_waitset_swap(
_Inout_ dds_attachment **dst,
_In_ dds_attachment **src,
_In_opt_ dds_attachment *prev,
_In_ dds_attachment *idx)
{
/* Remove from source. */
if (prev == NULL) {
*src = idx->next;
} else {
prev->next = idx->next;
}
/* Add to destination. */
idx->next = *dst;
*dst = idx;
}
static void
dds_waitset_signal_entity(
_In_ dds_waitset *ws)
{
dds_entity *e = (dds_entity*)ws;
/* When signaling any observers of us through the entity,
* we need to be unlocked. We still have claimed the related
* handle, so possible deletions will be delayed until we
* release it. */
os_mutexUnlock(&(e->m_mutex));
dds_entity_status_signal(e);
os_mutexLock(&(e->m_mutex));
}
static dds_return_t
dds_waitset_wait_impl(
_In_ dds_entity_t waitset,
_Out_writes_to_opt_(nxs, return < 0 ? 0 : return) dds_attach_t *xs,
_In_ size_t nxs,
_In_ dds_time_t abstimeout,
_In_ dds_time_t tnow)
{
dds_waitset *ws;
dds_return_t ret;
dds__retcode_t rc;
dds_attachment *idx;
dds_attachment *next;
dds_attachment *prev;
if ((xs == NULL) && (nxs != 0)){
return DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "A size was given, but no array.");
}
if ((xs != NULL) && (nxs == 0)){
return DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Array is given with an invalid size");
}
/* Locking the waitset here will delay a possible deletion until it is
* unlocked. Even when the related mutex is unlocked by a conditioned wait. */
rc = dds_waitset_lock(waitset, &ws);
if (rc == DDS_RETCODE_OK) {
/* Check if any of any previous triggered entities has changed there status
* and thus it trigger value could be false now. */
idx = ws->triggered;
prev = NULL;
while (idx != NULL) {
next = idx->next;
if (idx->entity->m_trigger == 0) {
/* Move observed entity to triggered list. */
dds_waitset_swap(&(ws->observed), &(ws->triggered), prev, idx);
} else {
prev = idx;
}
idx = next;
}
/* Check if any of the entities have been triggered. */
idx = ws->observed;
prev = NULL;
while (idx != NULL) {
next = idx->next;
if (idx->entity->m_trigger > 0) {
/* Move observed entity to triggered list. */
dds_waitset_swap(&(ws->triggered), &(ws->observed), prev, idx);
} else {
prev = idx;
}
idx = next;
}
/* Only wait/keep waiting when whe have something to observer and there aren't any triggers yet. */
rc = DDS_RETCODE_OK;
while ((ws->observed != NULL) && (ws->triggered == NULL) && (rc == DDS_RETCODE_OK)) {
if (abstimeout == DDS_NEVER) {
os_condWait(&ws->m_entity.m_cond, &ws->m_entity.m_mutex);
} else if (abstimeout <= tnow) {
rc = DDS_RETCODE_TIMEOUT;
} else {
dds_duration_t dt = abstimeout - tnow;
os_time to;
if ((dt / (dds_duration_t)DDS_NSECS_IN_SEC) >= (dds_duration_t)OS_TIME_INFINITE_SEC) {
to.tv_sec = OS_TIME_INFINITE_SEC;
to.tv_nsec = DDS_NSECS_IN_SEC - 1;
} else {
to.tv_sec = (os_timeSec) (dt / DDS_NSECS_IN_SEC);
to.tv_nsec = (uint32_t) (dt % DDS_NSECS_IN_SEC);
}
(void)os_condTimedWait(&ws->m_entity.m_cond, &ws->m_entity.m_mutex, &to);
tnow = dds_time();
}
}
/* Get number of triggered entities
* - set attach array when needed
* - swap them back to observed */
if (rc == DDS_RETCODE_OK) {
ret = 0;
idx = ws->triggered;
while (idx != NULL) {
if ((uint32_t)ret < (uint32_t)nxs) {
xs[ret] = idx->arg;
}
ret++;
next = idx->next;
/* The idx is always the first in triggered, so no prev. */
dds_waitset_swap(&(ws->observed), &(ws->triggered), NULL, idx);
idx = next;
}
} else if (rc == DDS_RETCODE_TIMEOUT) {
ret = 0;
} else {
ret = DDS_ERRNO(rc, "Internal error");
}
dds_waitset_unlock(ws);
} else {
ret = DDS_ERRNO(rc, "Error occurred on locking waitset");
}
return ret;
}
static void
dds_waitset_close_list(
_In_ dds_attachment **list,
_In_ dds_entity_t waitset)
{
dds_attachment *idx = *list;
dds_attachment *next;
while (idx != NULL) {
next = idx->next;
(void)dds_entity_observer_unregister(idx->entity->m_hdl, waitset);
os_free(idx);
idx = next;
}
*list = NULL;
}
static bool
dds_waitset_remove_from_list(
_In_ dds_attachment **list,
_In_ dds_entity_t observed)
{
dds_attachment *idx = *list;
dds_attachment *prev = NULL;
while (idx != NULL) {
if (idx->entity->m_hdl == observed) {
if (prev == NULL) {
*list = idx->next;
} else {
prev->next = idx->next;
}
os_free(idx);
/* We're done. */
return true;
}
prev = idx;
idx = idx->next;
}
return false;
}
dds_return_t
dds_waitset_close(
struct dds_entity *e)
{
dds_waitset *ws = (dds_waitset*)e;
dds_waitset_close_list(&(ws->observed), e->m_hdl);
dds_waitset_close_list(&(ws->triggered), e->m_hdl);
/* Trigger waitset to wake up. */
os_condBroadcast(&e->m_cond);
return DDS_RETCODE_OK;
}
_Pre_satisfies_((participant & DDS_ENTITY_KIND_MASK) == DDS_KIND_PARTICIPANT)
DDS_EXPORT _Must_inspect_result_ dds_entity_t
dds_create_waitset(
_In_ dds_entity_t participant)
{
dds_entity_t hdl;
dds_entity *par;
dds__retcode_t rc;
DDS_REPORT_STACK();
rc = dds_entity_lock(participant, DDS_KIND_PARTICIPANT, &par);
if (rc == DDS_RETCODE_OK) {
dds_waitset *waitset = dds_alloc(sizeof(*waitset));
hdl = dds_entity_init(&waitset->m_entity, par, DDS_KIND_WAITSET, NULL, NULL, 0);
waitset->m_entity.m_deriver.close = dds_waitset_close;
waitset->observed = NULL;
waitset->triggered = NULL;
dds_entity_unlock(par);
} else {
hdl = DDS_ERRNO(rc, "Error occurred on locking entity");
}
DDS_REPORT_FLUSH(hdl <= 0);
return hdl;
}
_Pre_satisfies_((waitset & DDS_ENTITY_KIND_MASK) == DDS_KIND_WAITSET)
DDS_EXPORT dds_return_t
dds_waitset_get_entities(
_In_ dds_entity_t waitset,
_Out_writes_to_(size, return < 0 ? 0 : return) dds_entity_t *entities,
_In_ size_t size)
{
dds_return_t ret = 0;
dds__retcode_t rc;
dds_waitset *ws;
DDS_REPORT_STACK();
rc = dds_waitset_lock(waitset, &ws);
if (rc == DDS_RETCODE_OK) {
dds_attachment* iter;
iter = ws->observed;
while (iter) {
if (((size_t)ret < size) && (entities != NULL)) {
entities[ret] = iter->entity->m_hdl;
}
ret++;
iter = iter->next;
}
iter = ws->triggered;
while (iter) {
if (((size_t)ret < size) && (entities != NULL)) {
entities[ret] = iter->entity->m_hdl;
}
ret++;
iter = iter->next;
}
dds_waitset_unlock(ws);
} else {
ret = DDS_ERRNO(rc, "Error occurred on locking waitset");
}
DDS_REPORT_FLUSH(ret < 0);
return ret;
}
static void
dds_waitset_move(
_In_ dds_attachment **src,
_Inout_ dds_attachment **dst,
_In_ dds_entity_t entity)
{
dds_attachment *idx = *src;
dds_attachment *prev = NULL;
while (idx != NULL) {
if (idx->entity->m_hdl == entity) {
/* Swap idx from src to dst. */
dds_waitset_swap(dst, src, prev, idx);
/* We're done. */
return;
}
prev = idx;
idx = idx->next;
}
}
static void
dds_waitset_remove(
dds_waitset *ws,
dds_entity_t observed)
{
if (!dds_waitset_remove_from_list(&(ws->observed), observed)) {
(void)dds_waitset_remove_from_list(&(ws->triggered), observed);
}
}
/* This is called when the observed entity signals a status change. */
void
dds_waitset_observer(
dds_entity_t observer,
dds_entity_t observed,
uint32_t status)
{
dds_waitset *ws;
if (dds_waitset_lock(observer, &ws) == DDS_RETCODE_OK) {
if (status & DDS_DELETING_STATUS) {
/* Remove this observed entity, which is being deleted, from the waitset. */
dds_waitset_remove(ws, observed);
/* Our registration to this observed entity will be removed automatically. */
} else if (status != 0) {
/* Move observed entity to triggered list. */
dds_waitset_move(&(ws->observed), &(ws->triggered), observed);
} else {
/* Remove observed entity from triggered list (which it possibly resides in). */
dds_waitset_move(&(ws->triggered), &(ws->observed), observed);
}
/* Trigger waitset to wake up. */
os_condBroadcast(&ws->m_entity.m_cond);
dds_waitset_unlock(ws);
}
}
_Pre_satisfies_((waitset & DDS_ENTITY_KIND_MASK) == DDS_KIND_WAITSET)
DDS_EXPORT dds_return_t
dds_waitset_attach(
_In_ dds_entity_t waitset,
_In_ dds_entity_t entity,
_In_ dds_attach_t x)
{
dds_entity *e = NULL;
dds_waitset *ws;
dds__retcode_t rc;
dds_return_t ret;
DDS_REPORT_STACK();
rc = dds_waitset_lock(waitset, &ws);
if (rc == DDS_RETCODE_OK) {
if (waitset != entity) {
rc = dds_entity_lock(entity, DDS_KIND_DONTCARE, &e);
if (rc != DDS_RETCODE_OK) {
e = NULL;
}
} else {
e = (dds_entity*)ws;
}
/* This will fail if given entity is already attached (or deleted). */
if (rc == DDS_RETCODE_OK) {
rc = dds_entity_observer_register_nl(e, waitset, dds_waitset_observer);
}
if (rc == DDS_RETCODE_OK) {
dds_attachment *a = os_malloc(sizeof(dds_attachment));
a->arg = x;
a->entity = e;
if (e->m_trigger > 0) {
a->next = ws->triggered;
ws->triggered = a;
} else {
a->next = ws->observed;
ws->observed = a;
}
ret = DDS_RETCODE_OK;
} else if (rc != DDS_RETCODE_PRECONDITION_NOT_MET) {
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Entity is not valid");
} else {
ret = DDS_ERRNO(rc, "Entity is already attached.");
}
if ((e != NULL) && (waitset != entity)) {
dds_entity_unlock(e);
}
dds_waitset_unlock(ws);
} else {
ret = DDS_ERRNO(rc, "Error occurred on locking waitset");
}
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK );
return ret;
}
_Pre_satisfies_((waitset & DDS_ENTITY_KIND_MASK) == DDS_KIND_WAITSET)
DDS_EXPORT dds_return_t
dds_waitset_detach(
_In_ dds_entity_t waitset,
_In_ dds_entity_t entity)
{
dds_waitset *ws;
dds__retcode_t rc;
dds_return_t ret;
DDS_REPORT_STACK();
rc = dds_waitset_lock(waitset, &ws);
if (rc == DDS_RETCODE_OK) {
/* Possibly fails when entity was not attached. */
if (waitset == entity) {
rc = dds_entity_observer_unregister_nl((dds_entity*)ws, waitset);
} else {
rc = dds_entity_observer_unregister(entity, waitset);
}
if (rc == DDS_RETCODE_OK) {
dds_waitset_remove(ws, entity);
ret = DDS_RETCODE_OK;
} else if (rc != DDS_RETCODE_PRECONDITION_NOT_MET) {
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "The given entity to detach is invalid.");
} else {
ret = DDS_ERRNO(rc, "The given entity to detach was not attached previously.");
}
dds_waitset_unlock(ws);
} else {
ret = DDS_ERRNO(rc, "Error occurred on locking waitset");
}
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_((waitset & DDS_ENTITY_KIND_MASK) == DDS_KIND_WAITSET)
dds_return_t
dds_waitset_wait_until(
_In_ dds_entity_t waitset,
_Out_writes_to_opt_(nxs, return < 0 ? 0 : return) dds_attach_t *xs,
_In_ size_t nxs,
_In_ dds_time_t abstimeout)
{
dds_return_t ret;
DDS_REPORT_STACK();
ret = dds_waitset_wait_impl(waitset, xs, nxs, abstimeout, dds_time());
DDS_REPORT_FLUSH(ret <0 );
return ret;
}
_Pre_satisfies_((waitset & DDS_ENTITY_KIND_MASK) == DDS_KIND_WAITSET)
dds_return_t
dds_waitset_wait(
_In_ dds_entity_t waitset,
_Out_writes_to_opt_(nxs, return < 0 ? 0 : return) dds_attach_t *xs,
_In_ size_t nxs,
_In_ dds_duration_t reltimeout)
{
dds_entity_t ret;
DDS_REPORT_STACK();
if (reltimeout >= 0) {
dds_time_t tnow = dds_time();
dds_time_t abstimeout = (DDS_INFINITY - reltimeout <= tnow) ? DDS_NEVER : (tnow + reltimeout);
ret = dds_waitset_wait_impl(waitset, xs, nxs, abstimeout, tnow);
} else{
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Negative timeout");
}
DDS_REPORT_FLUSH(ret <0 );
return ret;
}
_Pre_satisfies_((waitset & DDS_ENTITY_KIND_MASK) == DDS_KIND_WAITSET)
dds_return_t
dds_waitset_set_trigger(
_In_ dds_entity_t waitset,
_In_ bool trigger)
{
dds_waitset *ws;
dds__retcode_t rc;
dds_return_t ret = DDS_RETCODE_OK;
DDS_REPORT_STACK();
/* Locking the waitset here will delay a possible deletion until it is
* unlocked. Even when the related mutex is unlocked when we want to send
* a signal. */
rc = dds_waitset_lock(waitset, &ws);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking waitset");
goto fail;
}
if (trigger) {
dds_entity_status_set(ws, DDS_WAITSET_TRIGGER_STATUS);
} else {
dds_entity_status_reset(ws, DDS_WAITSET_TRIGGER_STATUS);
}
dds_waitset_signal_entity(ws);
dds_waitset_unlock(ws);
fail:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}

View file

@ -0,0 +1,406 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include "dds__writer.h"
#include "dds__write.h"
#include "dds__tkmap.h"
#include "ddsi/q_error.h"
#include "ddsi/q_thread.h"
#include "q__osplser.h"
#include "dds__err.h"
#include "ddsi/q_transmit.h"
#include "ddsi/q_ephash.h"
#include "ddsi/q_config.h"
#include "ddsi/q_entity.h"
#include "dds__report.h"
#include "ddsi/q_radmin.h"
#include <string.h>
#if OS_ATOMIC64_SUPPORT
typedef os_atomic_uint64_t fake_seq_t;
uint64_t fake_seq_next (fake_seq_t *x) { return os_atomic_inc64_nv (x); }
#else /* HACK */
typedef os_atomic_uint32_t fake_seq_t;
uint64_t fake_seq_next (fake_seq_t *x) { return os_atomic_inc32_nv (x); }
#endif
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
dds_return_t
dds_write(
_In_ dds_entity_t writer,
_In_ const void *data)
{
dds_return_t ret;
dds__retcode_t rc;
dds_writer *wr;
DDS_REPORT_STACK();
if (data != NULL) {
rc = dds_writer_lock(writer, &wr);
if (rc == DDS_RETCODE_OK) {
ret = dds_write_impl(wr, data, dds_time(), 0);
dds_writer_unlock(wr);
} else {
ret = DDS_ERRNO(rc, "Error occurred on locking entity");
}
} else {
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "No data buffer provided");
}
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
int
dds_writecdr(
dds_entity_t writer,
const void *cdr,
size_t size)
{
dds_return_t ret;
dds__retcode_t rc;
dds_writer *wr;
if (cdr != NULL) {
rc = dds_writer_lock(writer, &wr);
if (rc == DDS_RETCODE_OK) {
ret = dds_writecdr_impl (wr, cdr, size, dds_time (), 0);
dds_writer_unlock(wr);
} else {
ret = DDS_ERRNO(rc, "Error occurred on locking writer");
}
} else{
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Given cdr has NULL value");
}
return ret;
}
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
dds_return_t
dds_write_ts(
_In_ dds_entity_t writer,
_In_ const void *data,
_In_ dds_time_t timestamp)
{
dds_return_t ret;
dds__retcode_t rc;
dds_writer *wr;
DDS_REPORT_STACK();
if(data == NULL){
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument data has NULL value");
goto err;
}
if(timestamp < 0){
ret = DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Argument timestamp has negative value");
goto err;
}
rc = dds_writer_lock(writer, &wr);
if (rc == DDS_RETCODE_OK) {
ret = dds_write_impl(wr, data, timestamp, 0);
dds_writer_unlock(wr);
} else {
ret = DDS_ERRNO(rc, "Error occurred on locking writer");
}
err:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
static void
init_sampleinfo(
_Out_ struct nn_rsample_info *sampleinfo,
_In_ struct writer *wr,
_In_ int64_t seq,
_In_ serdata_t payload)
{
memset(sampleinfo, 0, sizeof(*sampleinfo));
sampleinfo->bswap = 0;
sampleinfo->complex_qos = 0;
sampleinfo->hashash = 0;
sampleinfo->seq = seq;
sampleinfo->reception_timestamp = payload->v.msginfo.timestamp;
sampleinfo->statusinfo = payload->v.msginfo.statusinfo;
sampleinfo->pwr_info.iid = 1;
sampleinfo->pwr_info.auto_dispose = 0;
sampleinfo->pwr_info.guid = wr->e.guid;
sampleinfo->pwr_info.ownership_strength = 0;
}
static int
deliver_locally(
_In_ struct writer *wr,
_In_ int64_t seq,
_In_ serdata_t payload,
_In_ struct tkmap_instance *tk)
{
dds_return_t ret = DDS_RETCODE_OK;
os_mutexLock (&wr->rdary.rdary_lock);
if (wr->rdary.fastpath_ok) {
struct reader ** const rdary = wr->rdary.rdary;
if (rdary[0]) {
struct nn_rsample_info sampleinfo;
unsigned i;
init_sampleinfo(&sampleinfo, wr, seq, payload);
for (i = 0; rdary[i]; i++) {
bool stored;
TRACE (("reader %x:%x:%x:%x\n", PGUID (rdary[i]->e.guid)));
dds_duration_t max_block_ms = nn_from_ddsi_duration(wr->xqos->reliability.max_blocking_time) / DDS_NSECS_IN_MSEC;
do {
stored = (ddsi_plugin.rhc_store_fn) (rdary[i]->rhc, &sampleinfo, payload, tk);
if (!stored) {
if (max_block_ms <= 0) {
ret = DDS_ERRNO(DDS_RETCODE_TIMEOUT, "The writer could not deliver data on time, probably due to a local reader resources being full.");
} else {
dds_sleepfor(DDS_MSECS(DDS_HEADBANG_TIMEOUT_MS));
}
/* Decreasing the block time after the sleep, let's us possibly
* wait a bit too long. But that's preferable compared to waiting
* a bit too short. */
max_block_ms -= DDS_HEADBANG_TIMEOUT_MS;
}
} while ((!stored) && (ret == DDS_RETCODE_OK));
}
}
os_mutexUnlock (&wr->rdary.rdary_lock);
} else {
/* When deleting, pwr is no longer accessible via the hash
tables, and consequently, a reader may be deleted without
it being possible to remove it from rdary. The primary
reason rdary exists is to avoid locking the proxy writer
but this is less of an issue when we are deleting it, so
we fall back to using the GUIDs so that we can deliver all
samples we received from it. As writer being deleted any
reliable samples that are rejected are simply discarded. */
ut_avlIter_t it;
struct pwr_rd_match *m;
struct nn_rsample_info sampleinfo;
os_mutexUnlock (&wr->rdary.rdary_lock);
init_sampleinfo(&sampleinfo, wr, seq, payload);
os_mutexLock (&wr->e.lock);
for (m = ut_avlIterFirst (&wr_local_readers_treedef, &wr->local_readers, &it); m != NULL; m = ut_avlIterNext (&it)) {
struct reader *rd;
if ((rd = ephash_lookup_reader_guid (&m->rd_guid)) != NULL) {
TRACE (("reader-via-guid %x:%x:%x:%x\n", PGUID (rd->e.guid)));
/* Copied the return value ignore from DDSI deliver_user_data() function. */
(void)(ddsi_plugin.rhc_store_fn) (rd->rhc, &sampleinfo, payload, tk);
}
}
os_mutexUnlock (&wr->e.lock);
}
return ret;
}
int
dds_write_impl(
_In_ dds_writer *wr,
_In_ const void * data,
_In_ dds_time_t tstamp,
_In_ dds_write_action action)
{
static fake_seq_t fake_seq;
dds_return_t ret = DDS_RETCODE_OK;
int w_rc;
assert (wr);
assert (dds_entity_kind(((dds_entity*)wr)->m_hdl) == DDS_KIND_WRITER);
struct thread_state1 * const thr = lookup_thread_state ();
const bool asleep = !vtime_awake_p (thr->vtime);
const bool writekey = action & DDS_WR_KEY_BIT;
dds_writer * writer = (dds_writer*) wr;
struct writer * ddsi_wr = writer->m_wr;
struct tkmap_instance * tk;
serdata_t d;
if (data == NULL) {
return DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "No data buffer provided");
}
/* Check for topic filter */
if (ddsi_wr->topic->filter_fn && ! writekey) {
if (!(ddsi_wr->topic->filter_fn) (data, ddsi_wr->topic->filter_ctx)) {
goto filtered;
}
}
if (asleep) {
thread_state_awake (thr);
}
/* Serialize and write data or key */
if (writekey) {
d = serialize_key (gv.serpool, ddsi_wr->topic, data);
} else {
d = serialize (gv.serpool, ddsi_wr->topic, data);
}
/* Set if disposing or unregistering */
d->v.msginfo.statusinfo = ((action & DDS_WR_DISPOSE_BIT ) ? NN_STATUSINFO_DISPOSE : 0) |
((action & DDS_WR_UNREGISTER_BIT) ? NN_STATUSINFO_UNREGISTER : 0) ;
d->v.msginfo.timestamp.v = tstamp;
os_mutexLock (&writer->m_call_lock);
ddsi_serdata_ref(d);
tk = (ddsi_plugin.rhc_lookup_fn) (d);
w_rc = write_sample_gc (writer->m_xp, ddsi_wr, d, tk);
if (w_rc >= 0) {
/* Flush out write unless configured to batch */
if (! config.whc_batch){
nn_xpack_send (writer->m_xp, false);
}
ret = DDS_RETCODE_OK;
} else if (w_rc == ERR_TIMEOUT) {
ret = DDS_ERRNO(DDS_RETCODE_TIMEOUT, "The writer could not deliver data on time, probably due to a reader resources being full.");
} else if (w_rc == ERR_INVALID_DATA) {
ret = DDS_ERRNO(DDS_RETCODE_ERROR, "Invalid data provided");
} else {
ret = DDS_ERRNO(DDS_RETCODE_ERROR, "Internal error");
}
os_mutexUnlock (&writer->m_call_lock);
if (ret == DDS_RETCODE_OK) {
ret = deliver_locally (ddsi_wr, fake_seq_next(&fake_seq), d, tk);
}
ddsi_serdata_unref(d);
(ddsi_plugin.rhc_unref_fn) (tk);
if (asleep) {
thread_state_asleep (thr);
}
filtered:
return ret;
}
int
dds_writecdr_impl(
_In_ dds_writer *wr,
_In_ const void *cdr,
_In_ size_t sz,
_In_ dds_time_t tstamp,
_In_ dds_write_action action)
{
static fake_seq_t fake_seq;
int ret = DDS_RETCODE_OK;
int w_rc;
assert (wr);
assert (cdr);
struct thread_state1 * const thr = lookup_thread_state ();
const bool asleep = !vtime_awake_p (thr->vtime);
const bool writekey = action & DDS_WR_KEY_BIT;
struct writer * ddsi_wr = wr->m_wr;
struct tkmap_instance * tk;
serdata_t d;
/* Check for topic filter */
if (ddsi_wr->topic->filter_fn && ! writekey) {
abort();
}
if (asleep) {
thread_state_awake (thr);
}
/* Serialize and write data or key */
if (writekey) {
abort();
//d = serialize_key (gv.serpool, ddsi_wr->topic, data);
} else {
serstate_t st = ddsi_serstate_new (gv.serpool, ddsi_wr->topic);
if (ddsi_wr->topic->nkeys) {
abort();
//dds_key_gen ((const dds_topic_descriptor_t*) tp->type, &st->data->v.keyhash, (char*) sample);
}
ddsi_serstate_append_blob(st, 1, sz, cdr);
d = ddsi_serstate_fix(st);
}
/* Set if disposing or unregistering */
d->v.msginfo.statusinfo = ((action & DDS_WR_DISPOSE_BIT ) ? NN_STATUSINFO_DISPOSE : 0) |
((action & DDS_WR_UNREGISTER_BIT) ? NN_STATUSINFO_UNREGISTER : 0) ;
d->v.msginfo.timestamp.v = tstamp;
os_mutexLock (&wr->m_call_lock);
ddsi_serdata_ref(d);
tk = (ddsi_plugin.rhc_lookup_fn) (d);
w_rc = write_sample_gc (wr->m_xp, ddsi_wr, d, tk);
if (w_rc >= 0) {
/* Flush out write unless configured to batch */
if (! config.whc_batch) {
nn_xpack_send (wr->m_xp, false);
}
ret = DDS_RETCODE_OK;
} else if (w_rc == ERR_TIMEOUT) {
ret = DDS_ERRNO(DDS_RETCODE_TIMEOUT, "The writer could not deliver data on time, probably due to a reader resources being full.");
} else if (w_rc == ERR_INVALID_DATA) {
ret = DDS_ERRNO(DDS_RETCODE_ERROR, "Invalid data provided");
} else {
ret = DDS_ERRNO(DDS_RETCODE_ERROR, "Internal error");
}
os_mutexUnlock (&wr->m_call_lock);
if (ret == DDS_RETCODE_OK) {
ret = deliver_locally (ddsi_wr, fake_seq_next(&fake_seq), d, tk);
}
ddsi_serdata_unref(d);
(ddsi_plugin.rhc_unref_fn) (tk);
if (asleep) {
thread_state_asleep (thr);
}
return ret;
}
void
dds_write_set_batch(
bool enable)
{
config.whc_batch = enable ? 1 : 0;
}
_Pre_satisfies_((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER)
void
dds_write_flush(
dds_entity_t writer)
{
dds_return_t ret = DDS_RETCODE_OK;
dds__retcode_t rc;
DDS_REPORT_STACK();
struct thread_state1 * const thr = lookup_thread_state ();
const bool asleep = !vtime_awake_p (thr->vtime);
dds_writer *wr;
if (asleep) {
thread_state_awake (thr);
}
rc = dds_writer_lock(writer, &wr);
if (rc == DDS_RETCODE_OK) {
nn_xpack_send (wr->m_xp, true);
dds_writer_unlock(wr);
ret = DDS_RETCODE_OK;
} else{
ret = DDS_ERRNO(rc, "Error occurred on locking writer");
}
if (asleep) {
thread_state_asleep (thr);
}
DDS_REPORT_FLUSH(ret < 0);
return ;
}

View file

@ -0,0 +1,611 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include "ddsc/dds.h"
#include "ddsi/q_config.h"
#include "ddsi/q_entity.h"
#include "ddsi/q_thread.h"
#include "q__osplser.h"
#include "dds__writer.h"
#include "dds__listener.h"
#include "dds__qos.h"
#include "dds__err.h"
#include "dds__init.h"
#include "dds__tkmap.h"
#include "dds__report.h"
#include "ddsc/ddsc_project.h"
#define DDS_WRITER_STATUS_MASK \
DDS_LIVELINESS_LOST_STATUS |\
DDS_OFFERED_DEADLINE_MISSED_STATUS |\
DDS_OFFERED_INCOMPATIBLE_QOS_STATUS |\
DDS_PUBLICATION_MATCHED_STATUS
static dds_return_t
dds_writer_instance_hdl(
dds_entity *e,
dds_instance_handle_t *i)
{
assert(e);
assert(i);
*i = (dds_instance_handle_t)writer_instance_id(&e->m_guid);
return DDS_RETCODE_OK;
}
static dds_return_t
dds_writer_status_validate(
uint32_t mask)
{
return (mask & ~(DDS_WRITER_STATUS_MASK)) ?
DDS_ERRNO(DDS_RETCODE_BAD_PARAMETER, "Invalid status mask") :
DDS_RETCODE_OK;
}
/*
Handler function for all write related status callbacks. May trigger status
condition or call listener on writer. Each entity has a mask of
supported status types. According to DDS specification, if listener is called
then status conditions is not triggered.
*/
static void
dds_writer_status_cb(
void *entity,
const status_cb_data_t *data)
{
dds_writer *wr;
dds__retcode_t rc;
void *metrics = NULL;
/* When data is NULL, it means that the writer is deleted. */
if (data == NULL) {
/* Release the initial claim that was done during the create. This
* will indicate that further API deletion is now possible. */
ut_handle_release(((dds_entity*)entity)->m_hdl, ((dds_entity*)entity)->m_hdllink);
return;
}
DDS_REPORT_STACK();
if (dds_writer_lock(((dds_entity*)entity)->m_hdl, &wr) != DDS_RETCODE_OK) {
/* There's a deletion or closing going on. */
DDS_REPORT_FLUSH(false);
return;
}
assert(wr == entity);
/* Reset the status for possible Listener call.
* When a listener is not called, the status will be set (again). */
dds_entity_status_reset(entity, data->status);
/* Update status metrics. */
switch (data->status) {
case DDS_OFFERED_DEADLINE_MISSED_STATUS: {
wr->m_offered_deadline_missed_status.total_count++;
wr->m_offered_deadline_missed_status.total_count_change++;
wr->m_offered_deadline_missed_status.last_instance_handle = data->handle;
metrics = (void*)&(wr->m_offered_deadline_missed_status);
break;
}
case DDS_LIVELINESS_LOST_STATUS: {
wr->m_liveliness_lost_status.total_count++;
wr->m_liveliness_lost_status.total_count_change++;
metrics = (void*)&(wr->m_liveliness_lost_status);
break;
}
case DDS_OFFERED_INCOMPATIBLE_QOS_STATUS: {
wr->m_offered_incompatible_qos_status.total_count++;
wr->m_offered_incompatible_qos_status.total_count_change++;
wr->m_offered_incompatible_qos_status.last_policy_id = data->extra;
metrics = (void*)&(wr->m_offered_incompatible_qos_status);
break;
}
case DDS_PUBLICATION_MATCHED_STATUS: {
if (data->add) {
wr->m_publication_matched_status.total_count++;
wr->m_publication_matched_status.total_count_change++;
wr->m_publication_matched_status.current_count++;
wr->m_publication_matched_status.current_count_change++;
} else {
wr->m_publication_matched_status.current_count--;
wr->m_publication_matched_status.current_count_change--;
}
wr->m_publication_matched_status.last_subscription_handle = data->handle;
metrics = (void*)&(wr->m_publication_matched_status);
break;
}
default: assert (0);
}
/* The writer needs to be unlocked when propagating the (possible) listener
* call because the application should be able to call this writer within
* the callback function. */
dds_writer_unlock(wr);
/* Is anybody interested within the entity hierarchy through listeners? */
rc = dds_entity_listener_propagation(entity, entity, data->status, metrics, true);
if (rc == DDS_RETCODE_OK) {
/* Event was eaten by a listener. */
if (dds_writer_lock(((dds_entity*)entity)->m_hdl, &wr) == DDS_RETCODE_OK) {
assert(wr == entity);
/* Reset the status. */
dds_entity_status_reset(entity, data->status);
/* Reset the change counts of the metrics. */
switch (data->status) {
case DDS_OFFERED_DEADLINE_MISSED_STATUS: {
wr->m_offered_deadline_missed_status.total_count_change = 0;
break;
}
case DDS_LIVELINESS_LOST_STATUS: {
wr->m_liveliness_lost_status.total_count_change = 0;
break;
}
case DDS_OFFERED_INCOMPATIBLE_QOS_STATUS: {
wr->m_offered_incompatible_qos_status.total_count_change = 0;
break;
}
case DDS_PUBLICATION_MATCHED_STATUS: {
wr->m_publication_matched_status.total_count_change = 0;
wr->m_publication_matched_status.current_count_change = 0;
break;
}
default: assert (0);
}
dds_writer_unlock(wr);
} else {
/* There's a deletion or closing going on. */
}
} else if (rc == DDS_RETCODE_NO_DATA) {
/* Nobody was interested through a listener (NO_DATA == NO_CALL): set the status. */
dds_entity_status_set(entity, data->status);
/* Notify possible interested observers. */
dds_entity_status_signal(entity);
rc = DDS_RETCODE_OK;
} else if (rc == DDS_RETCODE_ALREADY_DELETED) {
/* An entity up the hierarchy is being deleted. */
rc = DDS_RETCODE_OK;
} else {
/* Something went wrong up the hierarchy. */
}
DDS_REPORT_FLUSH(rc != DDS_RETCODE_OK);
}
static uint32_t
get_bandwidth_limit(
nn_transport_priority_qospolicy_t transport_priority)
{
#ifdef DDSI_INCLUDE_NETWORK_CHANNELS
struct config_channel_listelem *channel = find_channel (transport_priority);
return channel->data_bandwidth_limit;
#else
return 0;
#endif
}
static dds_return_t
dds_writer_close(
dds_entity *e)
{
dds_return_t ret = DDS_RETCODE_OK;
dds_writer *wr = (dds_writer*)e;
struct thread_state1 * const thr = lookup_thread_state();
const bool asleep = thr ? !vtime_awake_p(thr->vtime) : false;
assert(e);
if (asleep) {
thread_state_awake(thr);
}
if (thr) {
nn_xpack_send (wr->m_xp, false);
}
if (delete_writer (&e->m_guid) != 0) {
ret = DDS_ERRNO(DDS_RETCODE_ERROR, "Internal error");
}
if (asleep) {
thread_state_asleep(thr);
}
return ret;
}
static dds_return_t
dds_writer_delete(
dds_entity *e)
{
dds_writer *wr = (dds_writer*)e;
struct thread_state1 * const thr = lookup_thread_state();
const bool asleep = thr ? !vtime_awake_p(thr->vtime) : false;
dds_return_t ret;
assert(e);
assert(thr);
if (asleep) {
thread_state_awake(thr);
}
if (thr) {
nn_xpack_free(wr->m_xp);
}
if (asleep) {
thread_state_asleep(thr);
}
ret = dds_delete(wr->m_topic->m_entity.m_hdl);
if(ret == DDS_RETCODE_OK){
ret = dds_delete_impl(e->m_parent->m_hdl, true);
if(dds_err_nr(ret) == DDS_RETCODE_ALREADY_DELETED){
ret = DDS_RETCODE_OK;
}
}
os_mutexDestroy(&wr->m_call_lock);
return ret;
}
static dds_return_t
dds_writer_qos_validate(
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = DDS_RETCODE_OK;
bool consistent = true;
assert(qos);
/* Check consistency. */
if(dds_qos_validate_common(qos) != true){
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Provided inconsistent QoS policy");
}
if((qos->present & QP_USER_DATA) && validate_octetseq(&qos->user_data) != true){
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "User Data QoS policy is inconsistent and caused an error");
}
if ((qos->present & QP_DURABILITY_SERVICE) && validate_durability_service_qospolicy(&qos->durability_service) != 0){
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Durability service QoS policy is inconsistent and caused an error");
}
if ((qos->present & QP_LIFESPAN) && validate_duration(&qos->lifespan.duration) != 0){
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Lifespan QoS policy is inconsistent and caused an error");
}
if ((qos->present & QP_HISTORY) && (qos->present & QP_RESOURCE_LIMITS) && (validate_history_and_resource_limits(&qos->history, &qos->resource_limits) != 0)){
ret = DDS_ERRNO(DDS_RETCODE_INCONSISTENT_POLICY, "Resource limits QoS policy is inconsistent and caused an error");
}
if(ret == DDS_RETCODE_OK && enabled) {
ret = dds_qos_validate_mutable_common(qos);
}
return ret;
}
static dds_return_t
dds_writer_qos_set(
dds_entity *e,
const dds_qos_t *qos,
bool enabled)
{
dds_return_t ret = dds_writer_qos_validate(qos, enabled);
if (ret == DDS_RETCODE_OK) {
/*
* TODO: CHAM-95: DDSI does not support changing QoS policies.
*
* Only Ownership is required for the minimum viable product. This seems
* to be the only QoS policy that DDSI supports changes on.
*/
if (qos->present & QP_OWNERSHIP_STRENGTH) {
dds_ownership_kind_t kind;
/* check for ownership before updating, ownership strength is applicable only if
* writer is exclusive */
dds_qget_ownership (e->m_qos, &kind);
if (kind == DDS_OWNERSHIP_EXCLUSIVE) {
struct thread_state1 * const thr = lookup_thread_state ();
const bool asleep = !vtime_awake_p (thr->vtime);
struct writer * ddsi_wr = ((dds_writer*)e)->m_wr;
dds_qset_ownership_strength (e->m_qos, qos->ownership_strength.value);
if (asleep) {
thread_state_awake (thr);
}
os_mutexLock (&((dds_writer*)e)->m_call_lock);
if (qos->ownership_strength.value != ddsi_wr->xqos->ownership_strength.value) {
ddsi_wr->xqos->ownership_strength.value = qos->ownership_strength.value;
}
os_mutexUnlock (&((dds_writer*)e)->m_call_lock);
if (asleep) {
thread_state_asleep (thr);
}
} else {
ret = DDS_ERRNO(DDS_RETCODE_ERROR, "Setting ownership strength doesn't make sense when the ownership is shared.");
}
} else {
if (enabled) {
ret = DDS_ERRNO(DDS_RETCODE_UNSUPPORTED, DDSC_PROJECT_NAME" does not support changing QoS policies yet");
}
}
}
return ret;
}
_Pre_satisfies_(((participant_or_publisher & DDS_ENTITY_KIND_MASK) == DDS_KIND_PUBLISHER) || \
((participant_or_publisher & DDS_ENTITY_KIND_MASK) == DDS_KIND_PARTICIPANT))
_Pre_satisfies_((topic & DDS_ENTITY_KIND_MASK) == DDS_KIND_TOPIC)
dds_entity_t
dds_create_writer(
_In_ dds_entity_t participant_or_publisher,
_In_ dds_entity_t topic,
_In_opt_ const dds_qos_t *qos,
_In_opt_ const dds_listener_t *listener)
{
dds__retcode_t rc;
dds_qos_t * wqos;
dds_writer * wr;
dds_entity_t writer;
dds_entity * pub = NULL;
dds_entity * tp;
dds_entity_t publisher;
struct thread_state1 * const thr = lookup_thread_state();
const bool asleep = !vtime_awake_p(thr->vtime);
ddsi_tran_conn_t conn = gv.data_conn_mc ? gv.data_conn_mc : gv.data_conn_uc;
dds_return_t ret;
DDS_REPORT_STACK();
/* Try claiming a participant. If that's not working, then it could be a subscriber. */
if(dds_entity_kind(participant_or_publisher) == DDS_KIND_PARTICIPANT){
publisher = dds_create_publisher(participant_or_publisher, qos, NULL);
} else{
publisher = participant_or_publisher;
}
rc = dds_entity_lock(publisher, DDS_KIND_PUBLISHER, &pub);
if (rc != DDS_RETCODE_OK) {
writer = DDS_ERRNO(rc, "Error occurred on locking publisher");
goto err_pub_lock;
}
if (publisher != participant_or_publisher) {
pub->m_flags |= DDS_ENTITY_IMPLICIT;
}
rc = dds_entity_lock(topic, DDS_KIND_TOPIC, &tp);
if (rc != DDS_RETCODE_OK) {
writer = DDS_ERRNO(rc, "Error occurred on locking topic");
goto err_tp_lock;
}
assert(((dds_topic*)tp)->m_stopic);
assert(pub->m_domain == tp->m_domain);
/* Merge Topic & Publisher qos */
wqos = dds_qos_create();
if (qos) {
/* Only returns failure when one of the qos args is NULL, which
* is not the case here. */
(void)dds_qos_copy(wqos, qos);
}
if (pub->m_qos) {
dds_qos_merge(wqos, pub->m_qos);
}
if (tp->m_qos) {
/* merge topic qos data to writer qos */
dds_qos_merge(wqos, tp->m_qos);
}
nn_xqos_mergein_missing(wqos, &gv.default_xqos_wr);
ret = dds_writer_qos_validate(wqos, false);
if (ret != 0) {
dds_qos_delete(wqos);
writer = ret;
goto err_bad_qos;
}
/* Create writer */
wr = dds_alloc(sizeof (*wr));
writer = dds_entity_init(&wr->m_entity, pub, DDS_KIND_WRITER, wqos, listener, DDS_WRITER_STATUS_MASK);
wr->m_topic = (dds_topic*)tp;
dds_entity_add_ref_nolock(tp);
wr->m_xp = nn_xpack_new(conn, get_bandwidth_limit(wqos->transport_priority), config.xpack_send_async);
os_mutexInit (&wr->m_call_lock);
wr->m_entity.m_deriver.close = dds_writer_close;
wr->m_entity.m_deriver.delete = dds_writer_delete;
wr->m_entity.m_deriver.set_qos = dds_writer_qos_set;
wr->m_entity.m_deriver.validate_status = dds_writer_status_validate;
wr->m_entity.m_deriver.get_instance_hdl = dds_writer_instance_hdl;
/* Extra claim of this writer to make sure that the delete waits until DDSI
* has deleted its writer as well. This can be known through the callback. */
if (ut_handle_claim(wr->m_entity.m_hdl, wr->m_entity.m_hdllink, DDS_KIND_WRITER, NULL) != UT_HANDLE_OK) {
assert(0);
}
os_mutexUnlock(&tp->m_mutex);
os_mutexUnlock(&pub->m_mutex);
if (asleep) {
thread_state_awake(thr);
}
wr->m_wr = new_writer(&wr->m_entity.m_guid, NULL, &pub->m_participant->m_guid, ((dds_topic*)tp)->m_stopic,
wqos, dds_writer_status_cb, wr);
os_mutexLock(&pub->m_mutex);
os_mutexLock(&tp->m_mutex);
assert(wr->m_wr);
if (asleep) {
thread_state_asleep(thr);
}
dds_entity_unlock(tp);
dds_entity_unlock(pub);
DDS_REPORT_FLUSH(writer <= 0);
return writer;
err_bad_qos:
dds_entity_unlock(tp);
err_tp_lock:
dds_entity_unlock(pub);
if((pub->m_flags & DDS_ENTITY_IMPLICIT) != 0){
(void)dds_delete(publisher);
}
err_pub_lock:
DDS_REPORT_FLUSH(writer <= 0);
return writer;
}
_Pre_satisfies_(((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER))
dds_entity_t
dds_get_publisher(
_In_ dds_entity_t writer)
{
dds_entity_t hdl = DDS_RETCODE_OK;
DDS_REPORT_STACK();
hdl = dds_valid_hdl(writer, DDS_KIND_WRITER);
if(hdl != DDS_RETCODE_OK){
hdl = DDS_ERRNO(hdl, "Provided handle is not writer kind, so it is not valid");
} else{
hdl = dds_get_parent(writer);
}
DDS_REPORT_FLUSH(hdl <= 0);
return hdl;
}
_Pre_satisfies_(((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER))
dds_return_t
dds_get_publication_matched_status (
_In_ dds_entity_t writer,
_Out_opt_ dds_publication_matched_status_t * status)
{
dds__retcode_t rc;
dds_writer *wr;
dds_return_t ret = DDS_RETCODE_OK;
DDS_REPORT_STACK();
rc = dds_writer_lock(writer, &wr);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking writer");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = wr->m_publication_matched_status;
}
if (((dds_entity*)wr)->m_status_enable & DDS_PUBLICATION_MATCHED_STATUS) {
wr->m_publication_matched_status.total_count_change = 0;
wr->m_publication_matched_status.current_count_change = 0;
dds_entity_status_reset(wr, DDS_PUBLICATION_MATCHED_STATUS);
}
dds_writer_unlock(wr);
fail:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_(((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER))
dds_return_t
dds_get_liveliness_lost_status (
_In_ dds_entity_t writer,
_Out_opt_ dds_liveliness_lost_status_t * status)
{
dds__retcode_t rc;
dds_writer *wr;
dds_return_t ret = DDS_RETCODE_OK;
DDS_REPORT_STACK();
rc = dds_writer_lock(writer, &wr);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking writer");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = wr->m_liveliness_lost_status;
}
if (((dds_entity*)wr)->m_status_enable & DDS_LIVELINESS_LOST_STATUS) {
wr->m_liveliness_lost_status.total_count_change = 0;
dds_entity_status_reset(wr, DDS_LIVELINESS_LOST_STATUS);
}
dds_writer_unlock(wr);
fail:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_(((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER))
dds_return_t
dds_get_offered_deadline_missed_status(
_In_ dds_entity_t writer,
_Out_opt_ dds_offered_deadline_missed_status_t *status)
{
dds__retcode_t rc;
dds_writer *wr;
dds_return_t ret = DDS_RETCODE_OK;
DDS_REPORT_STACK();
rc = dds_writer_lock(writer, &wr);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking writer");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = wr->m_offered_deadline_missed_status;
}
if (((dds_entity*)wr)->m_status_enable & DDS_OFFERED_DEADLINE_MISSED_STATUS) {
wr->m_offered_deadline_missed_status.total_count_change = 0;
dds_entity_status_reset(wr, DDS_OFFERED_DEADLINE_MISSED_STATUS);
}
dds_writer_unlock(wr);
fail:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}
_Pre_satisfies_(((writer & DDS_ENTITY_KIND_MASK) == DDS_KIND_WRITER))
dds_return_t
dds_get_offered_incompatible_qos_status (
_In_ dds_entity_t writer,
_Out_opt_ dds_offered_incompatible_qos_status_t * status)
{
dds__retcode_t rc;
dds_writer *wr;
dds_return_t ret = DDS_RETCODE_OK;
DDS_REPORT_STACK();
rc = dds_writer_lock(writer, &wr);
if (rc != DDS_RETCODE_OK) {
ret = DDS_ERRNO(rc, "Error occurred on locking writer");
goto fail;
}
/* status = NULL, application do not need the status, but reset the counter & triggered bit */
if (status) {
*status = wr->m_offered_incompatible_qos_status;
}
if (((dds_entity*)wr)->m_status_enable & DDS_OFFERED_INCOMPATIBLE_QOS_STATUS) {
wr->m_offered_incompatible_qos_status.total_count_change = 0;
dds_entity_status_reset(wr, DDS_OFFERED_INCOMPATIBLE_QOS_STATUS);
}
dds_writer_unlock(wr);
fail:
DDS_REPORT_FLUSH(ret != DDS_RETCODE_OK);
return ret;
}

View file

@ -0,0 +1,39 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef DDS_OSPLSER_H
#define DDS_OSPLSER_H
#include "ddsi/ddsi_ser.h"
#include "ddsi/q_xmsg.h"
#if defined (__cplusplus)
extern "C" {
#endif
int serdata_cmp (const struct serdata * a, const struct serdata * b);
uint32_t serdata_hash (const struct serdata *a);
serdata_t serialize (serstatepool_t pool, const struct sertopic * tp, const void * sample);
serdata_t serialize_key (serstatepool_t pool, const struct sertopic * tp, const void * sample);
void deserialize_into (void *sample, const struct serdata *serdata);
void free_deserialized (const struct serdata *serdata, void *vx);
void sertopic_free (struct sertopic * tp);
void serstate_set_key (serstate_t st, int justkey, const void *key);
void serstate_init (serstate_t st, const struct sertopic * topic);
void serstate_free (serstate_t st);
#if defined (__cplusplus)
}
#endif
#endif

View file

@ -0,0 +1,153 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include "os/os.h"
#include "dds__key.h"
#include "dds__tkmap.h"
#include "dds__stream.h"
#include "ddsi/q_bswap.h"
#include "q__osplser.h"
serdata_t serialize (serstatepool_t pool, const struct sertopic * tp, const void * sample)
{
dds_stream_t os;
serstate_t st = ddsi_serstate_new (pool, tp);
if (tp->nkeys)
{
dds_key_gen ((const dds_topic_descriptor_t*) tp->type, &st->data->v.keyhash, (char*) sample);
}
dds_stream_from_serstate (&os, st);
dds_stream_write_sample (&os, sample, tp);
dds_stream_add_to_serstate (&os, st);
return st->data;
}
int serdata_cmp (const struct serdata *a, const struct serdata *b)
{
/* First compare on topic */
if (a->v.st->topic != b->v.st->topic)
{
return a->v.st->topic < b->v.st->topic ? -1 : 1;
}
/* Samples with a keyless topic map to the default instance */
if
(
(a->v.st->topic) &&
(((dds_topic_descriptor_t*) a->v.st->topic->type)->m_keys == 0)
)
{
return 0;
}
/* Check key has been hashed */
assert (a->v.keyhash.m_flags & DDS_KEY_HASH_SET);
/* Compare by hash */
return memcmp (a->v.keyhash.m_hash, b->v.keyhash.m_hash, 16);
}
serdata_t serialize_key (serstatepool_t pool, const struct sertopic * tp, const void * sample)
{
serdata_t sd;
if (tp->nkeys)
{
dds_stream_t os;
dds_topic_descriptor_t * desc = (dds_topic_descriptor_t*) tp->type;
serstate_t st = ddsi_serstate_new (pool, tp);
dds_key_gen (desc, &st->data->v.keyhash, (char*) sample);
dds_stream_from_serstate (&os, st);
dds_stream_write_key (&os, sample, desc);
dds_stream_add_to_serstate (&os, st);
sd = st->data;
}
else
{
sd = serialize (pool, tp, sample);
}
sd->v.st->kind = STK_KEY;
return sd;
}
void deserialize_into (void * sample, const struct serdata * serdata)
{
const serstate_t st = serdata->v.st;
dds_stream_t is;
dds_stream_from_serstate (&is, st);
if (st->kind == STK_KEY)
{
dds_stream_read_key (&is, sample, (const dds_topic_descriptor_t*) st->topic->type);
}
else
{
dds_stream_read_sample (&is, sample, st->topic);
}
}
void serstate_set_key (serstate_t st, int justkey, const void *key)
{
st->kind = justkey ? STK_KEY : STK_DATA;
memcpy (&st->data->v.keyhash.m_hash, key, 16);
st->data->v.keyhash.m_flags = DDS_KEY_SET | DDS_KEY_HASH_SET | DDS_KEY_IS_HASH;
st->data->v.keyhash.m_key_len = 16;
}
void serstate_init (serstate_t st, const struct sertopic * topic)
{
st->pos = 0;
st->topic = topic;
st->kind = STK_DATA;
st->twrite.v = -1;
os_atomic_st32 (&st->refcount, 1);
if (topic)
{
os_atomic_inc32 (&(((struct sertopic *) topic)->refcount));
}
st->data->hdr.identifier = topic ?
(PLATFORM_IS_LITTLE_ENDIAN ? CDR_LE : CDR_BE) :
(PLATFORM_IS_LITTLE_ENDIAN ? PL_CDR_LE : PL_CDR_BE);
st->data->v.hash_valid = (topic == NULL || topic->nkeys) ? 0 : 1;
st->data->v.hash = 0;
st->data->v.bswap = false;
memset (st->data->v.keyhash.m_hash, 0, sizeof (st->data->v.keyhash.m_hash));
st->data->v.keyhash.m_key_len = 0;
st->data->v.keyhash.m_flags = 0;
}
void serstate_free (serstate_t st)
{
dds_free (st->data->v.keyhash.m_key_buff);
dds_free (st->data);
dds_free (st);
}
void sertopic_free (struct sertopic * tp)
{
if (tp && (os_atomic_dec32_nv (&tp->refcount) == 0))
{
dds_free (tp->name);
dds_free (tp->typename);
dds_free (tp->name_typename);
dds_sample_free (tp->filter_sample, (const struct dds_topic_descriptor *) tp->type, DDS_FREE_ALL);
dds_free (tp);
}
}

View file

@ -0,0 +1,33 @@
#
# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License v. 2.0 which is available at
# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
# v. 1.0 which is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
#
include(Criterion)
idlc_generate(RoundTrip RoundTrip.idl)
idlc_generate(Space Space.idl)
idlc_generate(TypesArrayKey TypesArrayKey.idl)
add_criterion_executable(criterion_ddsc .)
target_include_directories(criterion_ddsc PRIVATE
"$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/src/include/>")
target_link_libraries(criterion_ddsc RoundTrip Space TypesArrayKey ddsc OSAPI)
# Setup environment for config-tests
set(Criterion_ddsc_config_simple_udp_file "${CMAKE_CURRENT_LIST_DIR}/config_simple_udp.xml")
set(Criterion_ddsc_config_simple_udp_uri "file://${Criterion_ddsc_config_simple_udp_file}")
set(Criterion_ddsc_config_simple_udp_max_participants "0")
set_tests_properties(
Criterion_ddsc_config_simple_udp
PROPERTIES
REQUIRED_FILES ${Criterion_ddsc_config_simple_udp_file}
ENVIRONMENT "${CMAKE_PROJECT_NAME_CAPS}_URI=${Criterion_ddsc_config_simple_udp_uri};MAX_PARTICIPANTS=${Criterion_ddsc_config_simple_udp_max_participants}"
)
configure_file("config_env.h.in" "config_env.h")

View file

@ -0,0 +1,26 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
module RoundTripModule
{
struct DataType
{
sequence<octet> payload;
};
#pragma keylist DataType
struct Address
{
string ip;
long port;
};
#pragma keylist Address ip port
};

View file

@ -0,0 +1,40 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
module Space {
struct Type1 {
long long_1; //@Key
long long_2;
long long_3;
};
#pragma keylist Type1 long_1
struct Type2 {
long long_1; //@Key
long long_2;
long long_3;
};
#pragma keylist Type2 long_1
struct simpletypes {
long l;
long long ll;
unsigned short us;
unsigned long ul;
unsigned long long ull;
float f;
double d;
char c;
boolean b;
octet o;
string s; //@Key
};
#pragma keylist simpletypes s
};

View file

@ -0,0 +1,81 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
module TypesArrayKey {
struct long_arraytypekey {
long key[20]; //@Key
};
#pragma keylist long_arraytypekey key
typedef long long longlong;
struct longlong_arraytypekey {
longlong key[20]; //@Key
};
#pragma keylist longlong_arraytypekey key
typedef unsigned short unsignedshort;
struct unsignedshort_arraytypekey {
unsignedshort key[20]; //@Key
};
#pragma keylist unsignedshort_arraytypekey key
typedef unsigned long unsignedlong;
struct unsignedlong_arraytypekey {
unsignedlong key[20]; //@Key
};
#pragma keylist unsignedlong_arraytypekey key
typedef unsigned long long unsignedlonglong;
struct unsignedlonglong_arraytypekey {
unsignedlonglong key[20]; //@Key
};
#pragma keylist unsignedlonglong_arraytypekey key
struct float_arraytypekey {
float key[20]; //@Key
};
#pragma keylist float_arraytypekey key
struct double_arraytypekey {
double key[20]; //@Key
};
#pragma keylist double_arraytypekey key
struct char_arraytypekey {
char key[128]; //@Key
};
#pragma keylist char_arraytypekey key
struct boolean_arraytypekey {
boolean key[128]; //@Key
};
#pragma keylist boolean_arraytypekey key
struct octet_arraytypekey {
octet key[128]; //@Key
};
#pragma keylist octet_arraytypekey key
struct alltypeskey {
long l;
long long ll;
unsigned short us;
unsigned long ul;
unsigned long long ull;
float f;
double d;
char c;
boolean b;
octet o;
string s; //@Key
};
#pragma keylist alltypeskey l ll us ul ull f d c b o s
};

View file

@ -0,0 +1,28 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "ddsc/dds.h"
#include <criterion/criterion.h>
#include <criterion/logging.h>
Test(ddsc_basic, test)
{
dds_entity_t participant;
dds_return_t status;
participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0);
/* TODO: CHAM-108: Add some simple read/write test(s). */
status = dds_delete(participant);
cr_assert_eq(status, DDS_RETCODE_OK);
}

View file

@ -0,0 +1,842 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "RoundTrip.h"
#include "Space.h"
#include "ddsc/dds.h"
#include "os/os.h"
#include "test-common.h"
#include <criterion/criterion.h>
#include <criterion/logging.h>
static dds_entity_t g_participant = 0;
static dds_entity_t g_subscriber = 0;
static dds_entity_t g_publisher = 0;
static dds_entity_t g_topic = 0;
#define MAX_SAMPLES 1
static dds_sample_info_t g_info[MAX_SAMPLES];
static struct DDS_UserDataQosPolicy g_pol_userdata;
static struct DDS_TopicDataQosPolicy g_pol_topicdata;
static struct DDS_GroupDataQosPolicy g_pol_groupdata;
static struct DDS_DurabilityQosPolicy g_pol_durability;
static struct DDS_HistoryQosPolicy g_pol_history;
static struct DDS_ResourceLimitsQosPolicy g_pol_resource_limits;
static struct DDS_PresentationQosPolicy g_pol_presentation;
static struct DDS_LifespanQosPolicy g_pol_lifespan;
static struct DDS_DeadlineQosPolicy g_pol_deadline;
static struct DDS_LatencyBudgetQosPolicy g_pol_latency_budget;
static struct DDS_OwnershipQosPolicy g_pol_ownership;
static struct DDS_OwnershipStrengthQosPolicy g_pol_ownership_strength;
static struct DDS_LivelinessQosPolicy g_pol_liveliness;
static struct DDS_TimeBasedFilterQosPolicy g_pol_time_based_filter;
static struct DDS_PartitionQosPolicy g_pol_partition;
static struct DDS_ReliabilityQosPolicy g_pol_reliability;
static struct DDS_TransportPriorityQosPolicy g_pol_transport_priority;
static struct DDS_DestinationOrderQosPolicy g_pol_destination_order;
static struct DDS_WriterDataLifecycleQosPolicy g_pol_writer_data_lifecycle;
static struct DDS_ReaderDataLifecycleQosPolicy g_pol_reader_data_lifecycle;
static struct DDS_DurabilityServiceQosPolicy g_pol_durability_service;
static const char* c_userdata = "user_key";
static const char* c_topicdata = "topic_key";
static const char* c_groupdata = "group_key";
static const char* c_partitions[] = {"Partition1", "Partition2"};
static dds_qos_t *g_qos = NULL;
static void
qos_init(void)
{
g_qos = dds_qos_create();
cr_assert_not_null(g_qos);
g_pol_userdata.value._buffer = dds_alloc(strlen(c_userdata) + 1);
g_pol_userdata.value._length = (uint32_t)strlen(c_userdata) + 1;
g_pol_userdata.value._release = true;
g_pol_userdata.value._maximum = 0;
g_pol_topicdata.value._buffer = dds_alloc(strlen(c_topicdata) + 1);
g_pol_topicdata.value._length = (uint32_t)strlen(c_topicdata) + 1;
g_pol_topicdata.value._release = true;
g_pol_topicdata.value._maximum = 0;
g_pol_groupdata.value._buffer = dds_alloc(strlen(c_groupdata) + 1);
g_pol_groupdata.value._length = (uint32_t)strlen(c_groupdata) + 1;
g_pol_groupdata.value._release = true;
g_pol_groupdata.value._maximum = 0;
g_pol_history.kind = DDS_KEEP_LAST_HISTORY_QOS;
g_pol_history.depth = 1;
g_pol_resource_limits.max_samples = 1;
g_pol_resource_limits.max_instances = 1;
g_pol_resource_limits.max_samples_per_instance = 1;
g_pol_presentation.access_scope = DDS_INSTANCE_PRESENTATION_QOS;
g_pol_presentation.coherent_access = true;
g_pol_presentation.ordered_access = true;
g_pol_lifespan.duration.sec = 10000;
g_pol_lifespan.duration.nanosec = 11000;
g_pol_deadline.period.sec = 20000;
g_pol_deadline.period.nanosec = 220000;
g_pol_latency_budget.duration.sec = 30000;
g_pol_latency_budget.duration.nanosec = 33000;
g_pol_ownership.kind = DDS_EXCLUSIVE_OWNERSHIP_QOS;
g_pol_ownership_strength.value = 10;
g_pol_liveliness.kind = DDS_AUTOMATIC_LIVELINESS_QOS;
g_pol_liveliness.lease_duration.sec = 40000;
g_pol_liveliness.lease_duration.nanosec = 44000;
g_pol_time_based_filter.minimum_separation.sec = 50000;
g_pol_time_based_filter.minimum_separation.nanosec = 55000;
g_pol_partition.name._buffer = (char**)c_partitions;
g_pol_partition.name._length = 2;
g_pol_reliability.kind = DDS_RELIABLE_RELIABILITY_QOS;
g_pol_reliability.max_blocking_time.sec = 60000;
g_pol_reliability.max_blocking_time.nanosec = 66000;
g_pol_transport_priority.value = 42;
g_pol_destination_order.kind = DDS_BY_SOURCE_TIMESTAMP_DESTINATIONORDER_QOS;
g_pol_writer_data_lifecycle.autodispose_unregistered_instances = true;
g_pol_reader_data_lifecycle.autopurge_disposed_samples_delay.sec = 70000;
g_pol_reader_data_lifecycle.autopurge_disposed_samples_delay.nanosec= 77000;
g_pol_reader_data_lifecycle.autopurge_nowriter_samples_delay.sec = 80000;
g_pol_reader_data_lifecycle.autopurge_nowriter_samples_delay.nanosec = 88000;
g_pol_durability_service.history_depth = 1;
g_pol_durability_service.history_kind = DDS_KEEP_LAST_HISTORY_QOS;
g_pol_durability_service.max_samples = 2;
g_pol_durability_service.max_instances = 3;
g_pol_durability_service.max_samples_per_instance = 4;
g_pol_durability_service.service_cleanup_delay.sec = 90000;
g_pol_durability_service.service_cleanup_delay.nanosec = 99000;
}
static void
qos_fini(void)
{
dds_qos_delete(g_qos);
dds_free(g_pol_userdata.value._buffer);
dds_free(g_pol_groupdata.value._buffer);
dds_free(g_pol_topicdata.value._buffer);
}
static void
setup(void)
{
qos_init();
g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(g_participant, 0, "Failed to create prerequisite g_participant");
g_topic = dds_create_topic(g_participant, &RoundTripModule_DataType_desc, "RoundTrip", NULL, NULL);
cr_assert_gt(g_topic, 0, "Failed to create prerequisite g_topic");
g_subscriber = dds_create_subscriber(g_participant, NULL, NULL);
cr_assert_gt(g_subscriber, 0, "Failed to create prerequisite g_subscriber");
g_publisher = dds_create_publisher(g_participant, NULL, NULL);
cr_assert_gt(g_publisher, 0, "Failed to create prerequisite g_publisher");
}
static void
teardown(void)
{
qos_fini();
dds_delete(g_participant);
}
#define T_MILLISECOND 1000000ll
#define T_SECOND (1000 * T_MILLISECOND)
int64_t from_ddsi_duration (DDS_Duration_t x)
{
int64_t t;
t = x.sec * 10^9 + x.nanosec;
return t;
}
static void
check_default_qos_of_builtin_entity(dds_entity_t entity)
{
dds_return_t ret;
int64_t deadline;
int64_t liveliness_lease_duration;
int64_t minimum_separation;
int64_t max_blocking_time;
int64_t autopurge_nowriter_samples_delay;
int64_t autopurge_disposed_samples_delay;
dds_durability_kind_t durability_kind;
dds_presentation_access_scope_kind_t presentation_access_scope_kind;
dds_ownership_kind_t ownership_kind;
dds_liveliness_kind_t liveliness_kind;
dds_reliability_kind_t reliability_kind;
dds_destination_order_kind_t destination_order_kind;
dds_history_kind_t history_kind;
char **partitions;
uint32_t plen;
dds_qos_t *qos = dds_qos_create();
cr_assert_not_null(qos);
ret = dds_get_qos(entity, qos);
cr_assert_eq(ret, DDS_RETCODE_OK, "Failed to get QOS of builtin entity");
dds_qget_durability(qos, &durability_kind);
dds_qget_presentation(qos, &presentation_access_scope_kind, &g_pol_presentation.coherent_access, &g_pol_presentation.ordered_access);
dds_qget_deadline(qos, &deadline);
dds_qget_ownership(qos, &ownership_kind);
dds_qget_liveliness(qos, &liveliness_kind, &liveliness_lease_duration);
dds_qget_time_based_filter(qos, &minimum_separation);
dds_qget_reliability(qos, &reliability_kind, &max_blocking_time);
dds_qget_destination_order(qos, &destination_order_kind);
dds_qget_history(qos, &history_kind, &g_pol_history.depth);
dds_qget_resource_limits(qos, &g_pol_resource_limits.max_samples, &g_pol_resource_limits.max_instances, &g_pol_resource_limits.max_samples_per_instance);
dds_qget_reader_data_lifecycle(qos, &autopurge_nowriter_samples_delay, &autopurge_disposed_samples_delay);
dds_qget_partition(qos, &plen, &partitions);
// no getter for ENTITY_FACTORY
if ((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_SUBSCRIBER) {
cr_expect_eq(plen, 1);
if (plen > 0) {
cr_expect_str_eq(partitions[0], "__BUILT-IN PARTITION__");
}
} else if ((entity & DDS_ENTITY_KIND_MASK) == DDS_KIND_READER) {
cr_expect_eq(durability_kind, DDS_DURABILITY_TRANSIENT_LOCAL);
cr_expect_eq(presentation_access_scope_kind, DDS_PRESENTATION_TOPIC);
cr_expect_eq(g_pol_presentation.coherent_access, false);
cr_expect_eq(g_pol_presentation.ordered_access, false);
cr_expect_eq(deadline, DDS_INFINITY);
cr_expect_eq(ownership_kind, DDS_OWNERSHIP_SHARED);
cr_expect_eq(liveliness_kind, DDS_LIVELINESS_AUTOMATIC);
cr_expect_eq(minimum_separation, 0);
cr_expect_eq(reliability_kind, DDS_RELIABILITY_RELIABLE);
cr_expect_eq(max_blocking_time, DDS_MSECS(100));
cr_expect_eq(destination_order_kind, DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP);
cr_expect_eq(history_kind, DDS_HISTORY_KEEP_LAST);
cr_expect_eq(g_pol_history.depth, 1);
cr_expect_eq(g_pol_resource_limits.max_instances, DDS_LENGTH_UNLIMITED);
cr_expect_eq(g_pol_resource_limits.max_samples, DDS_LENGTH_UNLIMITED);
cr_expect_eq(g_pol_resource_limits.max_samples_per_instance, DDS_LENGTH_UNLIMITED);
cr_expect_eq(autopurge_nowriter_samples_delay, DDS_INFINITY);
cr_expect_eq(autopurge_disposed_samples_delay, DDS_INFINITY);
} else {
cr_assert_fail("Unsupported entity kind %s", entity_kind_str(entity));
}
if (plen > 0) {
for (uint32_t i = 0; i < plen; i++) {
dds_free(partitions[i]);
}
dds_free(partitions);
}
dds_qos_delete(qos);
}
static dds_entity_t builtin_topic_handles[10];
Test(ddsc_builtin_topics, types_allocation)
{
#define TEST_ALLOC(type) do { \
DDS_##type##BuiltinTopicData *data = DDS_##type##BuiltinTopicData__alloc(); \
cr_expect_not_null(data, "Failed to allocate DDS_" #type "BuiltinTopicData"); \
DDS_##type##BuiltinTopicData_free(data, DDS_FREE_ALL); \
} while(0)
TEST_ALLOC(Participant);
TEST_ALLOC(CMParticipant);
TEST_ALLOC(Type);
TEST_ALLOC(Topic);
TEST_ALLOC(Publication);
TEST_ALLOC(CMPublisher);
TEST_ALLOC(Subscription);
TEST_ALLOC(CMSubscriber);
TEST_ALLOC(CMDataWriter);
TEST_ALLOC(CMDataReader);
#undef TEST_ALLOC
}
Test(ddsc_builtin_topics, availability_builtin_topics, .init = setup, .fini = teardown)
{
dds_entity_t topic;
topic = dds_find_topic(g_participant, "DCPSParticipant");
cr_assert_gt(topic, 0);
dds_delete(topic);
topic = dds_find_topic(g_participant, "DCPSTopic");
cr_assert_lt(topic, 0);
//TODO CHAM-347: dds_delete(topic);
topic = dds_find_topic(g_participant, "DCPSType");
cr_assert_lt(topic, 0);
//TODO CHAM-347: dds_delete(topic);
topic = dds_find_topic(g_participant, "DCPSSubscription");
cr_assert_lt(topic, 0);
//TODO CHAM-347: dds_delete(topic);
topic = dds_find_topic(g_participant, "DCSPPublication");
cr_assert_lt(topic, 0);
//TODO CHAM-347: dds_delete(topic);
}
Test(ddsc_builtin_topics, read_publication_data, .init = setup, .fini = teardown)
{
dds_entity_t reader;
#if 0 /* disabled pending CHAM-347 */
dds_return_t ret;
DDS_PublicationBuiltinTopicData *data;
#endif
void *samples[MAX_SAMPLES];
reader = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, NULL, NULL);
cr_assert_gt(reader, 0, "Failed to create a data reader for DDS_BUILTIN_TOPIC_DCPSPUBLICATION.");
samples[0] = DDS_PublicationBuiltinTopicData__alloc();
#if 0 /* disabled pending CHAM-347 */
ret = dds_read(reader, samples, g_info, MAX_SAMPLES, MAX_SAMPLES);
cr_assert_gt(ret, 0, "Failed to read samples DCPSPublication");
data = (DDS_PublicationBuiltinTopicData *)samples;
cr_assert_str_eq(data->topic_name, "DCPSPublication");
#endif
DDS_PublicationBuiltinTopicData_free(samples[0], DDS_FREE_ALL);
}
Test(ddsc_builtin_topics, create_reader)
{
dds_entity_t participant;
dds_entity_t t1;
/* Create a participant */
participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0, "dds_participant_create");
/*
* The topics are created by the middleware as soon as a participant
* is created.
*/
#define TEST_FIND(p, t) do { \
t1 = dds_find_topic(p, t); \
cr_expect_gt(t1, 0, "dds_find_topic(\"" t "\") returned a valid handle"); \
dds_delete(t1); \
} while(0);
/* A builtin-topic proxy is created 'on demand' and should not exist before a reader is created for it */
TEST_FIND(participant, "DCPSParticipant");
TEST_FIND(participant, "CMParticipant");
#undef TEST_FIND
/*
* TODO CHAM-347: Not all builtin topics are created at the start.
*/
#define TEST_NOTFOUND(p, t) do { \
t1 = dds_find_topic(p, t); \
cr_expect_lt(t1, 0, "dds_find_topic(\"" t "\") returned a valid handle"); \
} while(0);
/* A builtin-topic proxy is created 'on demand' and should not exist before a reader is created for it */
TEST_NOTFOUND(participant, "DCPSType");
TEST_NOTFOUND(participant, "DCPSTopic");
TEST_NOTFOUND(participant, "DCPSPublication");
TEST_NOTFOUND(participant, "CMPublisher");
TEST_NOTFOUND(participant, "DCPSSubscription");
TEST_NOTFOUND(participant, "CMSubscriber");
TEST_NOTFOUND(participant, "CMDataWriter");
TEST_NOTFOUND(participant, "CMDataReader");
#undef TEST_NOTFOUND
/* A reader is created by providing a special builtin-topic handle */
{
dds_entity_t readers[10];
dds_entity_t builtin_subscriber, s;
builtin_topic_handles[0] = DDS_BUILTIN_TOPIC_DCPSPARTICIPANT;
builtin_topic_handles[1] = DDS_BUILTIN_TOPIC_CMPARTICIPANT;
builtin_topic_handles[2] = DDS_BUILTIN_TOPIC_DCPSTYPE;
builtin_topic_handles[3] = DDS_BUILTIN_TOPIC_DCPSTOPIC;
builtin_topic_handles[4] = DDS_BUILTIN_TOPIC_DCPSPUBLICATION;
builtin_topic_handles[5] = DDS_BUILTIN_TOPIC_CMPUBLISHER;
builtin_topic_handles[6] = DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION;
builtin_topic_handles[7] = DDS_BUILTIN_TOPIC_CMSUBSCRIBER;
builtin_topic_handles[8] = DDS_BUILTIN_TOPIC_CMDATAWRITER;
builtin_topic_handles[9] = DDS_BUILTIN_TOPIC_CMDATAREADER;
for (int i = 0; i < 10; i++) {
readers[i] = dds_create_reader(participant, builtin_topic_handles[i], NULL, NULL);
cr_expect_gt(readers[i], 0, "Failed to created reader for builtin topic handle %d", builtin_topic_handles[i]);
if (i == 0) {
/* Check the parent of reader is a subscriber */
builtin_subscriber = dds_get_parent(readers[i]);
cr_assert_gt(builtin_subscriber, 0, "Failed to get parent of first builtin-reader (%s)", dds_err_str(builtin_subscriber));
cr_assert_eq(builtin_subscriber & DDS_ENTITY_KIND_MASK, DDS_KIND_SUBSCRIBER, "Parent is not a subscriber");
} else {
/* Check the parent of reader equals parent of first reader */
s = dds_get_parent(readers[i]);
cr_assert_gt(s, 0, "Failed to get parent of builtin-reader (%s)", dds_err_str(s));
cr_assert_eq(s, builtin_subscriber, "Parent subscriber of reader(%d) doesn't equal builtin-subscriber", i);
//dds_delete(s);
}
}
}
#define TEST_FOUND(p, t) do { \
t1 = dds_find_topic(p, t); \
cr_expect_gt(t1, 0, "dds_find_topic(\"" t "\") returned an invalid handle (%s)", dds_err_str(t1)); \
if (t1 > 0) { \
dds_delete(t1); \
} \
} while(0);
/* Builtin-topics proxies should now be created */
TEST_FOUND(participant, "DCPSParticipant");
TEST_FOUND(participant, "CMParticipant");
TEST_FOUND(participant, "DCPSType");
TEST_FOUND(participant, "DCPSTopic");
TEST_FOUND(participant, "DCPSPublication");
TEST_FOUND(participant, "CMPublisher");
TEST_FOUND(participant, "DCPSSubscription");
TEST_FOUND(participant, "CMSubscriber");
TEST_FOUND(participant, "CMDataWriter");
TEST_FOUND(participant, "CMDataReader");
#undef TEST_FOUND
dds_delete(participant);
}
Test(ddsc_builtin_topics, read_subscription_data, .init = setup, .fini = teardown)
{
dds_entity_t reader;
#if 0 /* not supported yet */
dds_return_t ret;
DDS_SubscriptionBuiltinTopicData *data;
#endif
void * samples[MAX_SAMPLES];
reader = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, NULL);
cr_assert_gt(reader, 0, "Failed to create a data reader for DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION.");
samples[0] = DDS_SubscriptionBuiltinTopicData__alloc();
#if 0 /* not supported yet */
ret = dds_read(reader, samples, g_info, MAX_SAMPLES, MAX_SAMPLES);
cr_assert_gt(ret, 0, "Failed to read samples DCPSSubscription");
data = (DDS_SubscriptionBuiltinTopicData *)samples;
cr_assert_str_eq(data->topic_name, "DCPSSubscription");
#endif
DDS_SubscriptionBuiltinTopicData_free(samples[0], DDS_FREE_ALL);
}
Test(ddsc_builtin_topics, read_participant_data, .init = setup, .fini = teardown)
{
dds_entity_t reader;
dds_return_t ret;
void * samples[MAX_SAMPLES];
reader = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSPARTICIPANT, NULL, NULL);
cr_assert_gt(reader, 0, "Failed to create a data reader for DDS_BUILTIN_TOPIC_DCPSPARTICIPANT.");
samples[0] = DDS_ParticipantBuiltinTopicData__alloc();
ret = dds_read(reader, samples, g_info, MAX_SAMPLES, MAX_SAMPLES);
cr_assert_gt(ret, 0, "Failed to read samples DCPSParticipant");
{
DDS_ParticipantBuiltinTopicData *data = (DDS_ParticipantBuiltinTopicData*)samples[0];
cr_log_info("Participant.key: %x.%x.%x\n", data->key[0], data->key[1], data->key[2]);
cr_log_info("Participant.userdata: %s\n", data->user_data.value._buffer);
}
DDS_ParticipantBuiltinTopicData_free(samples[0], DDS_FREE_ALL);
}
Test(ddsc_builtin_topics, read_cmparticipant_data, .init = setup, .fini = teardown)
{
dds_entity_t reader;
dds_return_t ret;
void * samples[MAX_SAMPLES];
reader = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_CMPARTICIPANT, NULL, NULL);
cr_assert_gt(reader, 0, "Failed to create a data reader for DDS_BUILTIN_TOPIC_DCPSPARTICIPANT.");
samples[0] = DDS_CMParticipantBuiltinTopicData__alloc();
ret = dds_read(reader, samples, g_info, MAX_SAMPLES, MAX_SAMPLES);
cr_assert_gt(ret, 0, "Failed to read samples CMParticipant");
{
DDS_CMParticipantBuiltinTopicData *data = (DDS_CMParticipantBuiltinTopicData*)samples[0];
cr_log_info("CMParticipant.key: %x.%x.%x\n", data->key[0], data->key[1], data->key[2]);
cr_log_info("CMParticipant.product: %s\n", data->product.value);
}
DDS_CMParticipantBuiltinTopicData_free(samples[0], DDS_FREE_ALL);
}
Test(ddsc_builtin_topics, read_topic_data, .init = setup, .fini = teardown)
{
dds_entity_t reader;
#if 0 /* disabled pending CHAM-347 */
dds_return_t ret;
DDS_TopicBuiltinTopicData *data;
#endif
void * samples[MAX_SAMPLES];
reader = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSTOPIC, NULL, NULL);
cr_assert_gt(reader, 0, "Failed to create a data reader for DDS_BUILTIN_TOPIC_DCPSTOPIC.");
samples[0] = DDS_TopicBuiltinTopicData__alloc();
#if 0 /* disabled pending CHAM-347 */
ret = dds_read(reader, samples, g_info, MAX_SAMPLES, MAX_SAMPLES);
cr_assert_gt(ret, 0, "Failed to read samples DCPSTopic");
data = (DDS_TopicBuiltinTopicData *)samples;
cr_assert_str_eq(data->name, "DCPSSubscription");
#endif
DDS_ParticipantBuiltinTopicData_free(samples[0], DDS_FREE_ALL);
}
Test(ddsc_builtin_topics, read_type_data, .init = setup, .fini = teardown)
{
dds_entity_t reader;
#if 0 /* disabled pending CHAM-347 */
dds_return_t ret;
DDS_TypeBuiltinTopicData *data;
#endif
void * samples[MAX_SAMPLES];
reader = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSTYPE, NULL, NULL);
cr_assert_gt(reader, 0, "Failed to create a data reader for DDS_BUILTIN_TOPIC_DCPSTYPE.");
samples[0] = DDS_TypeBuiltinTopicData__alloc();
#if 0 /* disabled pending CHAM-347 */
ret = dds_read(reader, samples, g_info, MAX_SAMPLES, MAX_SAMPLES);
cr_assert_gt(ret, 0, "Failed to read samples DCPSType");
data = (DDS_TypeBuiltinTopicData *)samples;
cr_assert_str_eq(data->name, "DCPSType");
#endif
DDS_TypeBuiltinTopicData_free(samples[0], DDS_FREE_ALL);
}
Test(ddsc_builtin_topics, same_subscriber, .init = setup, .fini = teardown)
{
dds_entity_t subscription_rdr;
dds_entity_t subscription_subscriber;
dds_entity_t publication_rdr;
dds_entity_t publication_subscriber;
dds_entity_t participant_rdr;
dds_entity_t participant_subscriber;
dds_entity_t topic_rdr;
dds_entity_t topic_subscriber;
dds_entity_t type_rdr;
dds_entity_t type_subscriber;
subscription_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, NULL);
cr_assert_gt(subscription_rdr, 0, "Failed to create a data reader for DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION.");
subscription_subscriber = dds_get_parent(subscription_rdr);
cr_assert_gt(subscription_subscriber, 0, "Could not find builtin subscriber for DSCPSSubscription-reader.");
publication_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, NULL, NULL);
cr_assert_gt(publication_rdr, 0, "Failed to create a data reader for DDS_BUILTIN_TOPIC_DCPSPUBLICATION.");
publication_subscriber = dds_get_parent(publication_rdr);
cr_assert_gt(publication_subscriber, 0, "Could not find builtin subscriber for DSCPSPublication-reader.");
cr_assert_eq(subscription_subscriber, publication_subscriber);
participant_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSPARTICIPANT, NULL, NULL);
cr_assert_gt(participant_rdr, 0, "Failed to create a data reader for DDS_BUILTIN_TOPIC_DCPSPARTICIPANT.");
participant_subscriber = dds_get_parent(participant_rdr);
cr_assert_gt(participant_subscriber, 0, "Could not find builtin subscriber for DSCPSParticipant-reader.");
cr_assert_eq(publication_subscriber, participant_subscriber);
topic_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSTOPIC, NULL, NULL);
cr_assert_gt(topic_rdr, 0, "Failed to create a data reader for DDS_BUILTIN_TOPIC_DCPSTOPIC.");
topic_subscriber = dds_get_parent(topic_rdr);
cr_assert_gt(topic_subscriber, 0, "Could not find builtin subscriber for DSCPSTopic-reader.");
cr_assert_eq(participant_subscriber, topic_subscriber);
type_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSTYPE, NULL, NULL);
cr_assert_gt(type_rdr, 0, "Failed to create a data reader for DDS_BUILTIN_TOPIC_DCPSTYPE.");
type_subscriber = dds_get_parent(type_rdr);
cr_assert_gt(type_subscriber, 0, "Could not find builtin subscriber for DSCPSType-reader.");
cr_assert_eq(topic_subscriber, type_subscriber);
}
Test(ddsc_builtin_topics, builtin_qos, .init = setup, .fini = teardown)
{
dds_entity_t dds_sub_rdr;
dds_entity_t dds_sub_subscriber;
dds_sub_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, NULL);
cr_assert_gt(dds_sub_rdr, 0, "Failed to create a data reader for DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION.");
check_default_qos_of_builtin_entity(dds_sub_rdr);
dds_sub_subscriber = dds_get_parent(dds_sub_rdr);
cr_assert_gt(dds_sub_subscriber, 0, "Could not find builtin subscriber for DSCPSSubscription-reader.");
check_default_qos_of_builtin_entity(dds_sub_subscriber);
}
Test(ddsc_builtin_topics, datareader_qos, .init = setup, .fini = teardown)
{
dds_entity_t rdr;
dds_entity_t subscription_rdr;
void * subscription_samples[MAX_SAMPLES];
#if 0 /* disabled pending CHAM-347 */
dds_return_t ret;
DDS_SubscriptionBuiltinTopicData *subscription_data;
#endif
// Set some qos' which differ from the default
dds_qset_durability(g_qos, (dds_durability_kind_t)g_pol_durability.kind);
dds_qset_deadline(g_qos, from_ddsi_duration(g_pol_deadline.period));
dds_qset_latency_budget(g_qos, from_ddsi_duration(g_pol_latency_budget.duration));
dds_qset_liveliness(g_qos, (dds_liveliness_kind_t)g_pol_liveliness.kind, from_ddsi_duration(g_pol_liveliness.lease_duration));
dds_qset_reliability(g_qos, (dds_reliability_kind_t)g_pol_reliability.kind, from_ddsi_duration(g_pol_reliability.max_blocking_time));
dds_qset_ownership(g_qos, (dds_ownership_kind_t)g_pol_ownership.kind);
dds_qset_destination_order(g_qos, (dds_destination_order_kind_t)g_pol_destination_order.kind);
dds_qset_userdata(g_qos, g_pol_userdata.value._buffer, g_pol_userdata.value._length);
dds_qset_time_based_filter(g_qos, from_ddsi_duration(g_pol_time_based_filter.minimum_separation));
dds_qset_presentation(g_qos, g_pol_presentation.access_scope, g_pol_presentation.coherent_access, g_pol_presentation.ordered_access);
dds_qset_partition(g_qos, g_pol_partition.name._length, c_partitions);
dds_qset_topicdata(g_qos, g_pol_topicdata.value._buffer, g_pol_topicdata.value._length);
dds_qset_groupdata(g_qos, g_pol_groupdata.value._buffer, g_pol_groupdata.value._length);
rdr = dds_create_reader(g_subscriber, g_topic, g_qos, NULL);
subscription_samples[0] = DDS_SubscriptionBuiltinTopicData__alloc();
subscription_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSSUBSCRIPTION, NULL, NULL);
cr_assert_gt(subscription_rdr, 0, "Failed to retrieve built-in datareader for DCPSSubscription");
#if 0 /* disabled pending CHAM-347 */
ret = dds_read(subscription_rdr, subscription_samples, g_info, MAX_SAMPLES, MAX_SAMPLES);
cr_assert_gt(ret, 0, "Failed to read Subscription data");
// Check the QOS settings of the 'remote' qos'
subscription_data = (DDS_SubscriptionBuiltinTopicData *)subscription_samples[0];
cr_assert_str_eq(subscription_data->topic_name, "RoundTrip");
cr_assert_str_eq(subscription_data->type_name, "RoundTripModule::DataType");
cr_assert_eq(subscription_data->durability.kind, g_pol_durability.kind);
cr_assert_eq(subscription_data->deadline.period.sec, g_pol_deadline.period.sec);
cr_assert_eq(subscription_data->deadline.period.nanosec, g_pol_deadline.period.nanosec);
cr_assert_eq(subscription_data->latency_budget.duration.sec, g_pol_latency_budget.duration.sec);
cr_assert_eq(subscription_data->latency_budget.duration.nanosec, g_pol_latency_budget.duration.nanosec);
cr_assert_eq(subscription_data->liveliness.kind, g_pol_liveliness.kind);
cr_assert_eq(subscription_data->liveliness.lease_duration.sec, g_pol_liveliness.lease_duration.sec);
cr_assert_eq(subscription_data->liveliness.lease_duration.nanosec, g_pol_liveliness.lease_duration.nanosec);
cr_assert_eq(subscription_data->reliability.kind, g_pol_reliability.kind);
cr_assert_eq(subscription_data->reliability.max_blocking_time.sec, g_pol_reliability.max_blocking_time.sec);
cr_assert_eq(subscription_data->reliability.max_blocking_time.nanosec, g_pol_reliability.max_blocking_time.nanosec);
cr_assert_eq(subscription_data->ownership.kind, g_pol_ownership.kind);
cr_assert_eq(subscription_data->destination_order.kind, g_pol_destination_order.kind);
cr_assert_eq(subscription_data->user_data.value._buffer, g_pol_userdata.value._buffer);
cr_assert_eq(subscription_data->user_data.value._length, g_pol_userdata.value._length);
cr_assert_eq(subscription_data->time_based_filter.minimum_separation.sec, g_pol_time_based_filter.minimum_separation.sec);
cr_assert_eq(subscription_data->time_based_filter.minimum_separation.nanosec, g_pol_time_based_filter.minimum_separation.nanosec);
cr_assert_eq(subscription_data->presentation.access_scope, g_pol_presentation.access_scope);
cr_assert_eq(subscription_data->presentation.coherent_access, g_pol_presentation.coherent_access);
cr_assert_eq(subscription_data->presentation.ordered_access, g_pol_presentation.ordered_access);
cr_assert_eq(subscription_data->partition.name._length, g_pol_partition.name._length);
for (uint32_t i = 0; i < subscription_data->partition.name._length; ++i)
{
cr_assert_str_eq(subscription_data->partition.name._buffer[i], c_partitions[i]);
}
cr_assert_str_eq(subscription_data->topic_data.value._buffer, g_pol_topicdata.value._buffer);
cr_assert_eq(subscription_data->topic_data.value._length, g_pol_topicdata.value._length);
cr_assert_str_eq(subscription_data->group_data.value._buffer, g_pol_groupdata.value._buffer);
cr_assert_eq(subscription_data->group_data.value._length, g_pol_groupdata.value._length);
#endif
DDS_SubscriptionBuiltinTopicData_free(subscription_samples[0], DDS_FREE_ALL);
}
Test(ddsc_builtin_topics, datawriter_qos, .init = setup, .fini = teardown)
{
dds_entity_t wrtr;
dds_entity_t publication_rdr;
#if 0 /* disabled pending CHAM-347 */
dds_return_t ret;
DDS_PublicationBuiltinTopicData *publication_data;
#endif
void * publication_samples[MAX_SAMPLES];
dds_qset_durability(g_qos, g_pol_durability.kind);
dds_qset_deadline(g_qos, from_ddsi_duration(g_pol_deadline.period));
dds_qset_latency_budget(g_qos, from_ddsi_duration(g_pol_latency_budget.duration));
dds_qset_liveliness(g_qos, (dds_liveliness_kind_t)g_pol_liveliness.kind, from_ddsi_duration(g_pol_liveliness.lease_duration));
dds_qset_reliability(g_qos, (dds_reliability_kind_t)g_pol_reliability.kind, from_ddsi_duration(g_pol_reliability.max_blocking_time));
dds_qset_lifespan(g_qos, from_ddsi_duration(g_pol_lifespan.duration));
dds_qset_destination_order(g_qos, (dds_destination_order_kind_t)g_pol_destination_order.kind);
dds_qset_userdata(g_qos, g_pol_userdata.value._buffer, g_pol_userdata.value._length);
dds_qset_ownership(g_qos, (dds_ownership_kind_t)g_pol_ownership.kind);
dds_qset_ownership_strength(g_qos, g_pol_ownership_strength.value);
dds_qset_presentation(g_qos, g_pol_presentation.access_scope, g_pol_presentation.coherent_access, g_pol_presentation.ordered_access);
dds_qset_partition(g_qos, g_pol_partition.name._length, c_partitions);
dds_qset_topicdata(g_qos, g_pol_topicdata.value._buffer, g_pol_topicdata.value._length);
wrtr = dds_create_writer(g_publisher, g_topic, g_qos, NULL);
publication_samples[0] = DDS_PublicationBuiltinTopicData__alloc();
publication_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSPUBLICATION, NULL, NULL);
cr_assert_gt(publication_rdr, 0, "Failed to retrieve built-in datareader for DCPSPublication");
#if 0 /* disabled pending CHAM-347 */
ret = dds_read(publication_rdr, publication_samples, g_info, MAX_SAMPLES, MAX_SAMPLES);
cr_assert_gt(ret, 0, "Failed to read Publication data");
// Check the QOS settings of the 'remote' qos'
publication_data = (DDS_PublicationBuiltinTopicData *)publication_samples[0];
cr_assert_str_eq(publication_data->topic_name, "RoundTrip");
cr_assert_str_eq(publication_data->type_name, "RoundTripModule::DataType");
cr_assert_eq(publication_data->durability.kind, g_pol_durability.kind);
cr_assert_eq(publication_data->deadline.period.sec, g_pol_deadline.period.sec);
cr_assert_eq(publication_data->deadline.period.nanosec, g_pol_deadline.period.nanosec);
cr_assert_eq(publication_data->latency_budget.duration.sec, g_pol_latency_budget.duration.sec);
cr_assert_eq(publication_data->latency_budget.duration.nanosec, g_pol_latency_budget.duration.nanosec);
cr_assert_eq(publication_data->liveliness.kind, g_pol_liveliness.kind);
cr_assert_eq(publication_data->liveliness.lease_duration.sec, g_pol_liveliness.lease_duration.sec);
cr_assert_eq(publication_data->liveliness.lease_duration.nanosec, g_pol_liveliness.lease_duration.nanosec);
cr_assert_eq(publication_data->reliability.kind, g_pol_reliability.kind);
cr_assert_eq(publication_data->reliability.max_blocking_time.sec, g_pol_reliability.max_blocking_time.sec);
cr_assert_eq(publication_data->reliability.max_blocking_time.nanosec, g_pol_reliability.max_blocking_time.nanosec);
cr_assert_eq(publication_data->lifespan.duration.sec, g_pol_lifespan.duration.sec);
cr_assert_eq(publication_data->lifespan.duration.nanosec, g_pol_lifespan.duration.nanosec);
cr_assert_eq(publication_data->destination_order.kind, g_pol_destination_order.kind);
cr_assert_eq(publication_data->user_data.value._buffer, g_pol_userdata.value._buffer);
cr_assert_eq(publication_data->user_data.value._length, g_pol_userdata.value._length);
cr_assert_eq(publication_data->ownership.kind, g_pol_ownership.kind);
cr_assert_eq(publication_data->ownership_strength.value, g_pol_ownership_strength.value);
cr_assert_eq(publication_data->presentation.access_scope, g_pol_presentation.access_scope);
cr_assert_eq(publication_data->presentation.coherent_access, g_pol_presentation.coherent_access);
cr_assert_eq(publication_data->presentation.ordered_access, g_pol_presentation.ordered_access);
cr_assert_eq(publication_data->partition.name._length, g_pol_partition.name._length);
for (uint32_t i = 0; i < publication_data->partition.name._length; ++i)
{
cr_assert_str_eq(publication_data->partition.name._buffer[i], c_partitions[i]);
}
cr_assert_str_eq(publication_data->topic_data.value._buffer, g_pol_topicdata.value._buffer);
cr_assert_eq(publication_data->topic_data.value._length, g_pol_topicdata.value._length);
cr_assert_str_eq(publication_data->group_data.value._buffer, g_pol_groupdata.value._buffer);
cr_assert_eq(publication_data->group_data.value._length, g_pol_groupdata.value._length);
#endif
DDS_PublicationBuiltinTopicData_free(publication_samples[0], DDS_FREE_ALL);
}
Test(ddsc_builtin_topics, topic_qos, .init = setup, .fini = teardown)
{
dds_entity_t tpc;
dds_entity_t topic_rdr;
#if 0 /* disabled pending CHAM-347 */
dds_return_t ret;
DDS_TopicBuiltinTopicData *topic_data;
#endif
void * topic_samples[MAX_SAMPLES];
dds_qset_durability(g_qos, g_pol_durability.kind);
dds_qset_durability_service(g_qos,
from_ddsi_duration(g_pol_durability_service.service_cleanup_delay),
(dds_history_kind_t)g_pol_durability_service.history_kind,
g_pol_durability_service.history_depth,
g_pol_durability_service.max_samples,
g_pol_durability_service.max_instances,
g_pol_durability_service.max_samples_per_instance);
dds_qset_deadline(g_qos, from_ddsi_duration(g_pol_deadline.period));
dds_qset_latency_budget(g_qos, from_ddsi_duration(g_pol_latency_budget.duration));
dds_qset_liveliness(g_qos, (dds_liveliness_kind_t)g_pol_liveliness.kind, from_ddsi_duration(g_pol_liveliness.lease_duration));
dds_qset_reliability(g_qos, (dds_reliability_kind_t)g_pol_reliability.kind, from_ddsi_duration(g_pol_reliability.max_blocking_time));
dds_qset_transport_priority(g_qos, g_pol_transport_priority.value);
dds_qset_lifespan(g_qos, from_ddsi_duration(g_pol_lifespan.duration));
dds_qset_destination_order(g_qos, (dds_destination_order_kind_t)g_pol_destination_order.kind);
dds_qset_history(g_qos, (dds_history_kind_t)g_pol_history.kind, g_pol_history.depth);
dds_qset_resource_limits(g_qos, g_pol_resource_limits.max_samples, g_pol_resource_limits.max_instances,
g_pol_resource_limits.max_samples_per_instance);
dds_qset_ownership(g_qos, (dds_ownership_kind_t)g_pol_ownership.kind);
dds_qset_topicdata(g_qos, g_pol_topicdata.value._buffer, g_pol_topicdata.value._length);
tpc = dds_create_topic(g_participant, &Space_Type1_desc, "SpaceType1", g_qos, NULL);
topic_samples[0] = DDS_PublicationBuiltinTopicData__alloc();
topic_rdr = dds_create_reader(g_participant, DDS_BUILTIN_TOPIC_DCPSTOPIC, NULL, NULL);
cr_assert_gt(topic_rdr, 0, "Failed to retrieve built-in datareader for DCPSPublication");
#if 0 /* disabled pending CHAM-347 */
ret = dds_read(topic_rdr, topic_samples, g_info, MAX_SAMPLES, MAX_SAMPLES);
cr_assert_gt(ret, 0, "Failed to read Topic data");
topic_data = (DDS_TopicBuiltinTopicData *)topic_samples[0];
cr_assert_str_eq(topic_data->name, "SpaceType1");
cr_assert_str_eq(topic_data->type_name, "RoundTripModule::DataType");
cr_assert_eq(topic_data->durability.kind, g_pol_durability.kind);
cr_assert_eq(topic_data->durability_service.service_cleanup_delay.sec, g_pol_durability_service.service_cleanup_delay.sec);
cr_assert_eq(topic_data->durability_service.service_cleanup_delay.nanosec, g_pol_durability_service.service_cleanup_delay.nanosec);
cr_assert_eq(topic_data->durability_service.history_kind, g_pol_durability_service.history_kind);
cr_assert_eq(topic_data->durability_service.history_depth, g_pol_durability_service.history_depth);
cr_assert_eq(topic_data->durability_service.max_samples, g_pol_durability_service.max_samples);
cr_assert_eq(topic_data->durability_service.max_instances, g_pol_durability_service.max_instances);
cr_assert_eq(topic_data->durability_service.max_samples_per_instance, g_pol_durability_service.max_samples_per_instance);
cr_assert_eq(topic_data->deadline.period.sec, g_pol_deadline.period.sec);
cr_assert_eq(topic_data->deadline.period.nanosec, g_pol_deadline.period.nanosec);
cr_assert_eq(topic_data->latency_budget.duration.sec, g_pol_latency_budget.duration.sec);
cr_assert_eq(topic_data->latency_budget.duration.nanosec, g_pol_latency_budget.duration.nanosec);
cr_assert_eq(topic_data->liveliness.kind, g_pol_liveliness.kind);
cr_assert_eq(topic_data->liveliness.lease_duration.sec, g_pol_liveliness.lease_duration.sec);
cr_assert_eq(topic_data->liveliness.lease_duration.nanosec, g_pol_liveliness.lease_duration.nanosec);
cr_assert_eq(topic_data->reliability.kind, g_pol_reliability.kind);
cr_assert_eq(topic_data->reliability.max_blocking_time.sec, g_pol_reliability.max_blocking_time.sec);
cr_assert_eq(topic_data->reliability.max_blocking_time.nanosec, g_pol_reliability.max_blocking_time.nanosec);
cr_assert_eq(topic_data->transport_priority.value, g_pol_transport_priority.value);
cr_assert_eq(topic_data->lifespan.duration.sec, g_pol_lifespan.duration.sec);
cr_assert_eq(topic_data->lifespan.duration.nanosec, g_pol_lifespan.duration.nanosec);
cr_assert_eq(topic_data->destination_order.kind, g_pol_destination_order.kind);
cr_assert_eq(topic_data->history.kind, g_pol_history.kind);
cr_assert_eq(topic_data->history.depth, g_pol_history.depth);
cr_assert_eq(topic_data->resource_limits.max_samples, g_pol_resource_limits.max_samples);
cr_assert_eq(topic_data->resource_limits.max_instances, g_pol_resource_limits.max_instances);
cr_assert_eq(topic_data->resource_limits.max_samples_per_instance, g_pol_resource_limits.max_samples_per_instance);
cr_assert_eq(topic_data->ownership.kind, g_pol_ownership.kind);
cr_assert_str_eq(topic_data->topic_data.value._buffer, g_pol_topicdata.value._buffer);
cr_assert_eq(topic_data->topic_data.value._length, g_pol_topicdata.value._length);
#endif
DDS_TopicBuiltinTopicData_free(topic_samples[0], DDS_FREE_ALL);
}

View file

@ -0,0 +1,79 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "ddsc/dds.h"
#include <criterion/criterion.h>
#include <criterion/logging.h>
#include "os/os.h"
#include "config_env.h"
#include "ddsc/ddsc_project.h"
#define FORCE_ENV
#define URI_VARIABLE DDSC_PROJECT_NAME_NOSPACE_CAPS"_URI"
#define MAX_PARTICIPANTS_VARIABLE "MAX_PARTICIPANTS"
static void config__check_env(
_In_z_ const char * env_variable,
_In_z_ const char * expected_value)
{
const char * env_uri = os_getenv(env_variable);
const char * const env_not_set = "Environment variable '%s' isn't set. This needs to be set to '%s' for this test to run.";
const char * const env_not_as_expected = "Environment variable '%s' has an unexpected value: '%s' (expected: '%s')";
#ifdef FORCE_ENV
{
bool env_ok;
if ( env_uri == NULL ) {
cr_log_info(env_not_set, env_variable, expected_value);
env_ok = false;
} else if ( strncmp(env_uri, expected_value, strlen(expected_value)) != 0 ) {
cr_log_info(env_not_as_expected, env_variable, env_uri, expected_value);
env_ok = false;
} else {
env_ok = true;
}
if ( !env_ok ) {
os_result r;
char *envstr;
envstr = os_malloc(strlen(env_variable) + strlen("=") + strlen(expected_value) + 1);
(void) sprintf(envstr, "%s=%s", env_variable, expected_value);
r = os_putenv(envstr);
cr_assert_eq(r, os_resultSuccess, "Invoking os_putenv(\"%s\") failed", envstr);
cr_log_warn("Environment variable '%s' set to expected value '%s'", env_variable, expected_value);
os_free(envstr);
}
}
#else
cr_assert_not_null(env_uri, env_not_set, env_variable, expected_value);
cr_assert_str_eq(env_uri, expected_value, env_not_as_expected, env_variable, env_uri, expected_value);
#endif /* FORCE_ENV */
}
Test(ddsc_config, simple_udp, .init = os_osInit, .fini = os_osExit) {
dds_entity_t participant;
config__check_env(URI_VARIABLE, CONFIG_ENV_SIMPLE_UDP);
config__check_env(MAX_PARTICIPANTS_VARIABLE, CONFIG_ENV_MAX_PARTICIPANTS);
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0, "dds_create_participant");
dds_delete(participant);
}

View file

@ -0,0 +1,18 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#ifndef CONFIG_ENV_H
#define CONFIG_ENV_H
#define CONFIG_ENV_SIMPLE_UDP "@Criterion_ddsc_config_simple_udp_uri@"
#define CONFIG_ENV_MAX_PARTICIPANTS "@Criterion_ddsc_config_simple_udp_max_participants@"
#endif /* CONFIG_ENV_H */

View file

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0 which is available at
http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
v. 1.0 which is available at
http://www.eclipse.org/org/documents/edl-v10.php.
SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
-->
<CycloneDDS>
<!-- Simple config-file for testing whether a config-file can be picked up
correctly. -->
<Domain>
<Id>3</Id>
</Domain>
<Lease>
<ExpiryTime update_factor="2e-1"/>
</Lease>
<DDSI2E>
<General>
<NetworkInterfaceAddress>127.0.0.1</NetworkInterfaceAddress>
<AllowMulticast>true</AllowMulticast>
<EnableMulticastLoopback>true</EnableMulticastLoopback>
<EnableLoopback>false</EnableLoopback>
</General>
<Compatibility>
<StandardsConformance>lax</StandardsConformance>
</Compatibility>
<Tracing>
<Verbosity>warning</Verbosity>
<OutputFile>&#118;&#x6F;rtexdds-<![CDATA[trace]]>.${NON_EXISTENT_ENV_VARIABLE:-l}${CYCLONEDDS_URI:+o}g </OutputFile>
</Tracing>
<Internal>
<MaxParticipants>${MAX_PARTICIPANTS}</MaxParticipants>
<HeartbeatInterval max="10 s"> 100 ms </HeartbeatInterval>
<RediscoveryBlacklistDuration></RediscoveryBlacklistDuration>
</Internal>
</DDSI2E>
</CycloneDDS>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,365 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "ddsc/dds.h"
#include <criterion/criterion.h>
#include <criterion/logging.h>
/* We are deliberately testing some bad arguments that SAL will complain about.
* So, silence SAL regarding these issues. */
#pragma warning(push)
#pragma warning(disable: 6387 28020)
/* Add --verbose command line argument to get the cr_log_info traces (if there are any). */
static dds_entity_t entity = -1;
#define cr_assert_status_eq(s1, s2, ...) cr_assert_eq(dds_err_nr(s1), s2, __VA_ARGS__)
/* Fixture to create prerequisite entity */
void create_entity(void)
{
cr_assert_eq(entity, -1, "entity already created pre create_entity fixture");
entity = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(entity, 0, "create_entity fixture failed");
}
/* Fixture to delete prerequisite entity */
void delete_entity(void)
{
cr_assert_gt(entity, 0, "entity not created pre delete_entity fixture");
dds_return_t ret = dds_delete(entity);
cr_assert_status_eq(ret, DDS_RETCODE_OK, "delete_entity fixture failed (ret: %d)", dds_err_nr(ret));
entity = -1;
}
Test(ddsc_entity, create, .fini = delete_entity)
{
/* Use participant as entity in the tests. */
entity = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(entity, 0, "dds_create_participant");
}
Test(ddsc_entity, enable, .init = create_entity, .fini = delete_entity)
{
dds_return_t status;
/* Check enabling with bad parameters. */
status = dds_enable(0);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_enable (NULL)");
/* Check actual enabling. */
/* TODO: CHAM-96: Check enabling.
status = dds_enable(&entity);
cr_assert_status_eq(status, dds_err_nr(DDS_RETCODE_OK), "dds_enable (delayed enable)");
*/
/* Check re-enabling (should be a noop). */
status = dds_enable(entity);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_enable (already enabled)");
}
void entity_qos_get_set(dds_entity_t e, const char* info)
{
dds_return_t status;
dds_qos_t *qos = dds_qos_create();
/* Get QoS. */
status = dds_get_qos (e, qos);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_get_qos(e, qos) ret: %d, %s", dds_err_nr(status), info);
status = dds_set_qos (e, qos); /* Doesn't change anything, so no need to forbid. But we return NOT_SUPPORTED anyway for now*/
cr_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED, "dds_set_qos(entity, qos) %s", info);
dds_qos_delete(qos);
}
Test(ddsc_entity, qos, .init = create_entity, .fini = delete_entity)
{
dds_return_t status;
dds_qos_t *qos = dds_qos_create();
/* Don't check inconsistent and immutable policies. That's a job
* for the specific entity children, not for the generic part. */
/* Check getting QoS with bad parameters. */
status = dds_get_qos (0, NULL);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_get_qos(NULL, NULL)");
status = dds_get_qos (entity, NULL);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_get_qos(entity, NULL)");
status = dds_get_qos (0, qos);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_get_qos(NULL, qos)");
/* Check setting QoS with bad parameters. */
status = dds_set_qos (0, NULL);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_set_qos(NULL, NULL)");
status = dds_set_qos (entity, NULL);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_set_qos(entity, NULL)");
status = dds_set_qos (0, qos);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_set_qos(NULL, qos)");
/* Check set/get with entity without initial qos. */
entity_qos_get_set(entity, "{without initial qos}");
/* Check set/get with entity with initial qos. */
{
dds_entity_t par = dds_create_participant (DDS_DOMAIN_DEFAULT, qos, NULL);
entity_qos_get_set(par, "{with initial qos}");
dds_delete(par);
}
/* Delete qos. */
dds_qos_delete(qos);
}
Test(ddsc_entity, listener, .init = create_entity, .fini = delete_entity)
{
dds_return_t status;
dds_listener_t *l1 = dds_listener_create(NULL);
dds_listener_t *l2 = dds_listener_create(NULL);
void *cb1;
void *cb2;
/* Don't check actual workings of the listeners. That's a job
* for the specific entity children, not for the generic part. */
/* Set some random values for the l2 listener callbacks.
* I know for sure that these will not be called within this test.
* Otherwise, the following would let everything crash.
* We just set them to know for sure that we got what we set. */
dds_lset_liveliness_changed(l2, (dds_on_liveliness_changed_fn) 1234);
dds_lset_requested_deadline_missed(l2, (dds_on_requested_deadline_missed_fn) 5678);
dds_lset_requested_incompatible_qos(l2, (dds_on_requested_incompatible_qos_fn) 8765);
dds_lset_publication_matched(l2, (dds_on_publication_matched_fn) 4321);
/* Check getting Listener with bad parameters. */
status = dds_get_listener (0, NULL);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_get_listener(NULL, NULL)");
status = dds_get_listener (entity, NULL);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_get_listener(entity, NULL)");
status = dds_get_listener (0, l1);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_get_listener(NULL, listener)");
/* Get Listener, which should be unset. */
status = dds_get_listener (entity, l1);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_get_listener(entity, listener)");
dds_lget_liveliness_changed (l1, (dds_on_liveliness_changed_fn*)&cb1);
cr_assert_eq(cb1, DDS_LUNSET, "Listener not initialized to NULL");
dds_lget_requested_deadline_missed (l1, (dds_on_requested_deadline_missed_fn*)&cb1);
cr_assert_eq(cb1, DDS_LUNSET, "Listener not initialized to NULL");
dds_lget_requested_incompatible_qos (l1, (dds_on_requested_incompatible_qos_fn*)&cb1);
cr_assert_eq(cb1, DDS_LUNSET, "Listener not initialized to NULL");
dds_lget_publication_matched (l1, (dds_on_publication_matched_fn*)&cb1);
cr_assert_eq(cb1, DDS_LUNSET, "Listener not initialized to NULL");
/* Check setting Listener with bad parameters. */
status = dds_set_listener (0, NULL);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_set_listener(NULL, NULL)");
status = dds_set_listener (0, l2);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_set_listener(NULL, listener)");
/* Getting after setting should return set listener. */
status = dds_set_listener (entity, l2);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_set_listener(entity, listener)");
status = dds_get_listener (entity, l1);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_get_listener(entity, listener)");
dds_lget_liveliness_changed (l1, (dds_on_liveliness_changed_fn*)&cb1);
dds_lget_liveliness_changed (l2, (dds_on_liveliness_changed_fn*)&cb2);
cr_assert_eq(cb1, cb2, "Listeners are not equal");
dds_lget_requested_deadline_missed (l1, (dds_on_requested_deadline_missed_fn*)&cb1);
dds_lget_requested_deadline_missed (l2, (dds_on_requested_deadline_missed_fn*)&cb2);
cr_assert_eq(cb1, cb2, "Listeners are not equal");
dds_lget_requested_incompatible_qos (l1, (dds_on_requested_incompatible_qos_fn*)&cb1);
dds_lget_requested_incompatible_qos (l2, (dds_on_requested_incompatible_qos_fn*)&cb2);
cr_assert_eq(cb1, cb2, "Listeners are not equal");
dds_lget_publication_matched (l1, (dds_on_publication_matched_fn*)&cb1);
dds_lget_publication_matched (l2, (dds_on_publication_matched_fn*)&cb2);
cr_assert_eq(cb1, cb2, "Listeners are not equal");
/* Reset listener. */
status = dds_set_listener (entity, NULL);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_set_listener(entity, NULL)");
status = dds_get_listener (entity, l2);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_get_listener(entity, listener)");
dds_lget_liveliness_changed (l2, (dds_on_liveliness_changed_fn*)&cb2);
cr_assert_eq(cb2, DDS_LUNSET, "Listener not reset");
dds_lget_requested_deadline_missed (l2, (dds_on_requested_deadline_missed_fn*)&cb2);
cr_assert_eq(cb2, DDS_LUNSET, "Listener not reset");
dds_lget_requested_incompatible_qos (l2, (dds_on_requested_incompatible_qos_fn*)&cb2);
cr_assert_eq(cb2, DDS_LUNSET, "Listener not reset");
dds_lget_publication_matched (l2, (dds_on_publication_matched_fn*)&cb2);
cr_assert_eq(cb2, DDS_LUNSET, "Listener not reset");
dds_free(l2);
dds_free(l1);
}
Test(ddsc_entity, status, .init = create_entity, .fini = delete_entity)
{
dds_return_t status1;
uint32_t s1 = 0;
/* Don't check actual bad statuses. That's a job
* for the specific entity children, not for the generic part. */
/* Check getting Status with bad parameters. */
status1 = dds_get_enabled_status (0, NULL);
cr_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER, "dds_get_enabled_status(NULL, NULL)");
status1 = dds_get_enabled_status (entity, NULL);
cr_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER, "dds_get_enabled_status(entity, NULL)");
status1 = dds_get_enabled_status (0, &s1);
cr_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER, "dds_get_enabled_status(NULL, status)");
/* Get Status, which should be 0 for a participant. */
status1 = dds_get_enabled_status (entity, &s1);
cr_assert_status_eq(status1, DDS_RETCODE_OK, "dds_get_enabled_status(entity, status)");
cr_assert_eq(s1, 0, "Enabled status mask is not 0");
/* Check setting Status with bad parameters. */
status1 = dds_set_enabled_status (0, 0);
cr_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER, "dds_set_enabled_status(NULL, 0)");
/* I shouldn't be able to set statuses on a participant. */
status1 = dds_set_enabled_status (entity, 0);
cr_assert_status_eq(status1, DDS_RETCODE_OK, "dds_set_enabled_status(entity, 0) %d", dds_err_nr(status1));
status1 = dds_set_enabled_status (entity, DDS_DATA_AVAILABLE_STATUS);
cr_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER, "dds_set_enabled_status(entity, status)");
/* Check getting Status changes with bad parameters. */
status1 = dds_get_status_changes (0, NULL);
cr_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER, "dds_get_status_changes(NULL, NULL)");
status1 = dds_get_status_changes (entity, NULL);
cr_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER, "dds_get_status_changes(entity, NULL)");
status1 = dds_get_status_changes (0, &s1);
cr_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER, "dds_get_status_changes(NULL, status)");
status1 = dds_get_status_changes (entity, &s1);
cr_assert_status_eq(status1, DDS_RETCODE_OK, "dds_get_status_changes(entity, status)");
/* Status read and take shouldn't work either. */
status1 = dds_read_status (0, &s1, 0);
cr_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER, "dds_read_status(NULL, status, 0)");
status1 = dds_read_status (entity, &s1, 0);
cr_assert_status_eq(status1, DDS_RETCODE_OK, "dds_read_status(entity, status, 0)");
status1 = dds_take_status (0, &s1, 0);
cr_assert_status_eq(status1, DDS_RETCODE_BAD_PARAMETER, "dds_take_status(NULL, status, 0)");
status1 = dds_take_status (entity, &s1, 0);
cr_assert_status_eq(status1, DDS_RETCODE_OK, "dds_take_status(entity, status, 0)");
}
Test(ddsc_entity, instance_handle, .init = create_entity, .fini = delete_entity)
{
dds_return_t status;
dds_instance_handle_t hdl;
/* Don't check actual handle contents. That's a job
* for the specific entity children, not for the generic part. */
/* Check getting Handle with bad parameters. */
status = dds_get_instance_handle (0, NULL);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_instancehandle_get(NULL, NULL)");
status = dds_get_instance_handle (entity, NULL);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_instancehandle_get(entity, NULL)");
status = dds_get_instance_handle (0, &hdl);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_instancehandle_get(NULL, handle)");
/* Get Instance Handle, which should not be 0 for a participant. */
status = dds_get_instance_handle (entity, &hdl);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_instancehandle_get(entity, handle)");
cr_assert_neq(hdl, 0, "Entity instance handle is 0");
}
Test(ddsc_entity, get_entities, .init = create_entity, .fini = delete_entity)
{
dds_return_t status;
dds_entity_t par;
dds_entity_t child;
/* ---------- Get Parent ------------ */
/* Check getting Parent with bad parameters. */
par = dds_get_parent (0);
cr_assert_eq(dds_err_nr(par), DDS_RETCODE_BAD_PARAMETER, "Parent was returned (despite of bad parameter)");
/* Get Parent, a participant doesn't have a parent. */
par = dds_get_parent (entity);
cr_assert_eq(dds_err_nr(par), DDS_ENTITY_NIL, "Parent was returned (despite of it being a participant)");
/* ---------- Get Participant ------------ */
/* Check getting Participant with bad parameters. */
par = dds_get_participant (0);
cr_assert_eq(dds_err_nr(par), DDS_RETCODE_BAD_PARAMETER, "Participant was returned (despite of bad parameter)");
/* Get Participant, a participants' participant is itself. */
par = dds_get_participant (entity);
cr_assert_eq(par, entity, "Returned participant was not expected");
/* ---------- Get Children ------------ */
/* Check getting Children with bad parameters. */
status = dds_get_children (0, &child, 1);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_get_children(NULL, child, 1)");
status = dds_get_children (entity, NULL, 1);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_get_children(entity, NULL, 1)");
status = dds_get_children (entity, &child, 0);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_get_children(entity, child, 0)");
status = dds_get_children (0, NULL, 1);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_get_children(NULL, NULL, 1)");
status = dds_get_children (0, &child, 0);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_get_children(NULL, child, 0)");
/* Get Children, of which there are currently none. */
status = dds_get_children (entity, NULL, 0);
if (status > 0) {
cr_assert("dds_get_children(entity, NULL, 0) un-expectantly found children");
} else {
cr_assert_eq(status, 0, "dds_get_children(entity, NULL, 0) failed");
}
status = dds_get_children (entity, &child, 1);
if (status > 0) {
cr_assert("dds_get_children(entity, child, 1) un-expectantly returned children");
} else {
cr_assert_eq(status, 0, "dds_get_children(entity, child, 1) failed");
}
}
Test(ddsc_entity, get_domainid, .init = create_entity, .fini = delete_entity)
{
dds_return_t status;
dds_domainid_t id;
/* Check getting ID with bad parameters. */
status = dds_get_domainid (0, NULL);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_get_domainid(NULL, NULL)");
status = dds_get_domainid (entity, NULL);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_get_domainid(entity, NULL)");
status = dds_get_domainid (0, &id);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_get_domainid(NULL, id)");
/* Get and check the domain id. */
status = dds_get_domainid (entity, &id);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_get_domainid(entity, id)");
cr_assert_eq(id, 0, "Different domain_id was returned than expected");
}
Test(ddsc_entity, delete, .init = create_entity)
{
dds_return_t status;
status = dds_delete(0);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_delete(NULL)");
status = dds_delete(entity);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_delete(entity)");
entity = 0;
}
#pragma warning(pop)

View file

@ -0,0 +1,995 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "ddsc/dds.h"
#include "os/os.h"
#include <criterion/criterion.h>
#include <criterion/logging.h>
#include <criterion/theories.h>
#include "RoundTrip.h"
/* Add --verbose command line argument to get the cr_log_info traces (if there are any). */
/**************************************************************************************************
*
* Test fixtures
*
*************************************************************************************************/
static dds_entity_t g_keep = 0;
static dds_entity_t g_participant = 0;
static dds_entity_t g_topic = 0;
static dds_entity_t g_subscriber = 0;
static dds_entity_t g_publisher = 0;
static dds_entity_t g_reader = 0;
static dds_entity_t g_writer = 0;
static dds_entity_t g_readcond = 0;
static dds_entity_t g_querycond = 0;
/* Dummy query condition callback. */
static bool
accept_all(const void * sample)
{
return true;
}
static char*
create_topic_name(const char *prefix, char *name, size_t size)
{
/* Get semi random g_topic name. */
os_procId pid = os_procIdSelf();
uintmax_t tid = os_threadIdToInteger(os_threadIdSelf());
(void) snprintf(name, size, "%s_pid%"PRIprocId"_tid%"PRIuMAX"", prefix, pid, tid);
return name;
}
static void
hierarchy_init(void)
{
uint32_t mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE;
char name[100];
g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(g_participant, 0, "Failed to create prerequisite g_participant");
g_topic = dds_create_topic(g_participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_hierarchy_test", name, sizeof name), NULL, NULL);
cr_assert_gt(g_topic, 0, "Failed to create prerequisite g_topic");
g_publisher = dds_create_publisher(g_participant, NULL, NULL);
cr_assert_gt(g_publisher, 0, "Failed to create prerequisite g_publisher");
g_subscriber = dds_create_subscriber(g_participant, NULL, NULL);
cr_assert_gt(g_subscriber, 0, "Failed to create prerequisite g_subscriber");
g_writer = dds_create_writer(g_publisher, g_topic, NULL, NULL);
cr_assert_gt(g_writer, 0, "Failed to create prerequisite g_writer");
g_reader = dds_create_reader(g_subscriber, g_topic, NULL, NULL);
cr_assert_gt(g_reader, 0, "Failed to create prerequisite g_reader");
g_readcond = dds_create_readcondition(g_reader, mask);
cr_assert_gt(g_readcond, 0, "Failed to create prerequisite g_readcond");
g_querycond = dds_create_querycondition(g_reader, mask, accept_all);
cr_assert_gt(g_querycond, 0, "Failed to create prerequisite g_querycond");
/* The deletion of the last participant will close down every thing. This
* means that the API will react differently after that. Because the
* testing we're doing here is quite generic, we'd like to not close down
* everything when we delete our participant. For that, we create a second
* participant, which will keep everything running.
*/
g_keep = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(g_keep, 0, "Failed to create prerequisite g_keep");
}
static void
hierarchy_fini(void)
{
dds_delete(g_querycond);
dds_delete(g_readcond);
dds_delete(g_reader);
dds_delete(g_writer);
dds_delete(g_subscriber);
dds_delete(g_publisher);
dds_delete(g_topic);
dds_delete(g_participant);
dds_delete(g_keep);
}
#if 0
#else
/**************************************************************************************************
*
* These will check the recursive deletion.
*
*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_delete, recursive, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_domainid_t id;
dds_return_t ret;
/* First be sure that 'dds_get_domainid' returns ok. */
ret = dds_get_domainid(g_participant, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_OK);
ret = dds_get_domainid(g_topic, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_OK);
ret = dds_get_domainid(g_publisher, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_OK);
ret = dds_get_domainid(g_subscriber, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_OK);
ret = dds_get_domainid(g_writer, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_OK);
ret = dds_get_domainid(g_reader, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_OK);
ret = dds_get_domainid(g_readcond, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_OK);
ret = dds_get_domainid(g_querycond, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_OK);
/* Deleting the top dog (participant) should delete all children. */
ret = dds_delete(g_participant);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_OK);
/* Check if all the entities are deleted now. */
ret = dds_get_domainid(g_participant, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED);
ret = dds_get_domainid(g_topic, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED);
ret = dds_get_domainid(g_publisher, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED);
ret = dds_get_domainid(g_subscriber, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED);
ret = dds_get_domainid(g_writer, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED);
ret = dds_get_domainid(g_reader, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED);
ret = dds_get_domainid(g_readcond, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED);
ret = dds_get_domainid(g_querycond, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_delete, recursive_with_deleted_topic)
{
dds_domainid_t id;
dds_return_t ret;
char name[100];
/* Internal handling of topic is different from all the other entities.
* It's very interesting if this recursive deletion still works and
* doesn't crash when the topic is already deleted (CHAM-424). */
/* First, create a topic and a writer with that topic. */
g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(g_participant, 0, "Failed to create prerequisite g_participant");
g_topic = dds_create_topic(g_participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_hierarchy_test", name, 100), NULL, NULL);
cr_assert_gt(g_topic, 0, "Failed to create prerequisite g_topic");
g_writer = dds_create_writer(g_participant, g_topic, NULL, NULL);
cr_assert_gt(g_writer, 0, "Failed to create prerequisite g_writer");
g_keep = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(g_keep, 0, "Failed to create prerequisite g_keep");
/* Second, delete the topic to make sure that the writer holds the last
* reference to the topic and thus will delete it when it itself is
* deleted. */
ret = dds_delete(g_topic);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_OK);
/* Third, deleting the participant should delete all children of which
* the writer with the last topic reference is one. */
ret = dds_delete(g_participant);
/* Before the CHAM-424 fix, we would not get here because of a crash,
* or it (incidentally) continued but returned an error. */
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_OK);
/* Check if the entities are actually deleted. */
ret = dds_get_domainid(g_participant, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED, "%s", dds_err_str(ret));
ret = dds_get_domainid(g_topic, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED);
ret = dds_get_domainid(g_writer, &id);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED);
dds_delete(g_keep);
}
/*************************************************************************************************/
/**************************************************************************************************
*
* These will check the dds_get_participant in various ways.
*
*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_participant, valid_entities) = {
DataPoints(dds_entity_t*, &g_readcond, &g_querycond, &g_reader, &g_subscriber, &g_writer, &g_publisher, &g_topic, &g_participant),
};
Theory((dds_entity_t *entity), ddsc_entity_get_participant, valid_entities, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t participant;
participant = dds_get_participant(*entity);
cr_assert_eq(participant, g_participant);
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_participant, deleted_entities) = {
DataPoints(dds_entity_t*, &g_readcond, &g_querycond, &g_reader, &g_subscriber, &g_writer, &g_publisher, &g_topic, &g_participant),
};
Theory((dds_entity_t *entity), ddsc_entity_get_participant, deleted_entities, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t participant;
dds_delete(*entity);
participant = dds_get_participant(*entity);
cr_assert_eq(dds_err_nr(participant), DDS_RETCODE_ALREADY_DELETED, "returned %d", dds_err_nr(participant));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_participant, invalid_entities) = {
DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN),
};
Theory((dds_entity_t entity), ddsc_entity_get_participant, invalid_entities, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1;
dds_entity_t participant;
participant = dds_get_participant(entity);
cr_assert_eq(dds_err_nr(participant), dds_err_nr(exp), "returned %d != expected %d", dds_err_nr(participant), dds_err_nr(exp));
}
/*************************************************************************************************/
/**************************************************************************************************
*
* These will check the dds_get_parent in various ways.
*
*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_parent, conditions) = {
DataPoints(dds_entity_t*, &g_readcond, &g_querycond),
};
Theory((dds_entity_t *entity), ddsc_entity_get_parent, conditions, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t parent;
parent = dds_get_parent(*entity);
cr_assert_eq(parent, g_reader);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_parent, reader, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t parent;
parent = dds_get_parent(g_reader);
cr_assert_eq(parent, g_subscriber);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_parent, writer, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t parent;
parent = dds_get_parent(g_writer);
cr_assert_eq(parent, g_publisher);
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_parent, pubsubtop) = {
DataPoints(dds_entity_t*, &g_publisher, &g_subscriber, &g_topic),
};
Theory((dds_entity_t *entity), ddsc_entity_get_parent, pubsubtop, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t parent;
parent = dds_get_parent(*entity);
cr_assert_eq(parent, g_participant);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_parent, participant, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t parent;
parent = dds_get_parent(g_participant);
cr_assert_eq(dds_err_nr(parent), DDS_ENTITY_NIL, "returned %d", dds_err_nr(parent));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_parent, deleted_entities) = {
DataPoints(dds_entity_t*, &g_readcond, &g_querycond, &g_reader, &g_subscriber, &g_writer, &g_publisher, &g_topic, &g_participant),
};
Theory((dds_entity_t *entity), ddsc_entity_get_parent, deleted_entities, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t parent;
dds_delete(*entity);
parent = dds_get_parent(*entity);
cr_assert_eq(dds_err_nr(parent), DDS_RETCODE_ALREADY_DELETED);
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_parent, invalid_entities) = {
DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN),
};
Theory((dds_entity_t entity), ddsc_entity_get_parent, invalid_entities, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1;
dds_entity_t parent;
parent = dds_get_parent(entity);
cr_assert_eq(dds_err_nr(parent), dds_err_nr(exp), "returned %d != expected %d", dds_err_nr(parent), dds_err_nr(exp));
}
/*************************************************************************************************/
/**************************************************************************************************
*
* These will check the dds_get_children in various ways.
*
*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_children, null, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_return_t ret;
ret = dds_get_children(g_participant, NULL, 0);
cr_assert_eq(ret, 3);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_children, invalid_size, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_return_t ret;
dds_entity_t child;
ret = dds_get_children(g_participant, &child, INT32_MAX);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_children, too_small, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_return_t ret;
dds_entity_t children[2];
ret = dds_get_children(g_participant, children, 2);
cr_assert_eq(ret, 3);
cr_assert((children[0] == g_publisher) || (children[0] == g_subscriber) || (children[0] == g_topic));
cr_assert((children[1] == g_publisher) || (children[1] == g_subscriber) || (children[1] == g_topic));
cr_assert_neq(children[0], children[1]);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_children, participant, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_return_t ret;
dds_entity_t children[4];
ret = dds_get_children(g_participant, children, 4);
cr_assert_eq(ret, 3);
cr_assert((children[0] == g_publisher) || (children[0] == g_subscriber) || (children[0] == g_topic));
cr_assert((children[1] == g_publisher) || (children[1] == g_subscriber) || (children[1] == g_topic));
cr_assert((children[2] == g_publisher) || (children[2] == g_subscriber) || (children[2] == g_topic));
cr_assert_neq(children[0], children[1]);
cr_assert_neq(children[0], children[2]);
cr_assert_neq(children[1], children[2]);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_children, topic, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_return_t ret;
dds_entity_t child;
ret = dds_get_children(g_topic, &child, 1);
cr_assert_eq(ret, 0);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_children, publisher, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_return_t ret;
dds_entity_t child;
ret = dds_get_children(g_publisher, &child, 1);
cr_assert_eq(ret, 1);
cr_assert_eq(child, g_writer);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_children, subscriber, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_return_t ret;
dds_entity_t children[2];
ret = dds_get_children(g_subscriber, children, 2);
cr_assert_eq(ret, 1);
cr_assert_eq(children[0], g_reader);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_children, writer, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_return_t ret;
ret = dds_get_children(g_writer, NULL, 0);
cr_assert_eq(ret, 0);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_children, reader, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_return_t ret;
dds_entity_t children[2];
ret = dds_get_children(g_reader, children, 2);
cr_assert_eq(ret, 2);
cr_assert((children[0] == g_readcond) || (children[0] == g_querycond));
cr_assert((children[1] == g_readcond) || (children[1] == g_querycond));
cr_assert_neq(children[0], children[1]);
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_children, conditions) = {
DataPoints(dds_entity_t*, &g_readcond, &g_querycond),
};
Theory((dds_entity_t *entity), ddsc_entity_get_children, conditions, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_return_t ret;
dds_entity_t child;
ret = dds_get_children(*entity, &child, 1);
cr_assert_eq(ret, 0);
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_children, deleted_entities) = {
DataPoints(dds_entity_t*, &g_readcond, &g_querycond, &g_reader, &g_subscriber, &g_writer, &g_publisher, &g_topic, &g_participant),
};
Theory((dds_entity_t *entity), ddsc_entity_get_children, deleted_entities, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_return_t ret;
dds_entity_t children[4];
dds_delete(*entity);
ret = dds_get_children(*entity, children, 4);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED);
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_children, invalid_entities) = {
DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN),
};
Theory((dds_entity_t entity), ddsc_entity_get_children, invalid_entities, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1;
dds_entity_t children[4];
dds_return_t ret;
ret = dds_get_children(entity, children, 4);
cr_assert_eq(dds_err_nr(ret), dds_err_nr(exp), "returned %d != expected %d", dds_err_nr(ret), dds_err_nr(exp));
}
/*************************************************************************************************/
/**************************************************************************************************
*
* These will check the dds_get_topic in various ways.
*
*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_topic, data_entities) = {
DataPoints(dds_entity_t*, &g_readcond, &g_querycond, &g_reader, &g_writer),
};
Theory((dds_entity_t *entity), ddsc_entity_get_topic, data_entities, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t topic;
topic = dds_get_topic(*entity);
cr_assert_eq(topic, g_topic );
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_topic, deleted_entities) = {
DataPoints(dds_entity_t*, &g_readcond, &g_querycond, &g_reader, &g_writer),
};
Theory((dds_entity_t *entity), ddsc_entity_get_topic, deleted_entities, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t topic;
dds_delete(*entity);
topic = dds_get_topic(*entity);
cr_assert_eq(dds_err_nr(topic), DDS_RETCODE_ALREADY_DELETED);
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_topic, invalid_entities) = {
DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN),
};
Theory((dds_entity_t entity), ddsc_entity_get_topic, invalid_entities, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1;
dds_entity_t topic;
topic = dds_get_topic(entity);
cr_assert_eq(dds_err_nr(topic), dds_err_nr(exp), "returned %d != expected %d", dds_err_nr(topic), dds_err_nr(exp));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_topic, non_data_entities) = {
DataPoints(dds_entity_t*, &g_subscriber, &g_publisher, &g_topic, &g_participant),
};
Theory((dds_entity_t *entity), ddsc_entity_get_topic, non_data_entities, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t topic;
topic = dds_get_topic(*entity);
cr_assert_eq(dds_err_nr(topic), DDS_RETCODE_ILLEGAL_OPERATION, "returned %d", dds_err_nr(topic));
}
/*************************************************************************************************/
/**************************************************************************************************
*
* These will check the dds_get_publisher in various ways.
*
*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_publisher, writer, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t publisher;
publisher = dds_get_publisher(g_writer);
cr_assert_eq(publisher, g_publisher);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_publisher, deleted_writer, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t publisher;
dds_delete(g_writer);
publisher = dds_get_publisher(g_writer);
cr_assert_eq(dds_err_nr(publisher), DDS_RETCODE_ALREADY_DELETED);
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_publisher, invalid_writers) = {
DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN),
};
Theory((dds_entity_t entity), ddsc_entity_get_publisher, invalid_writers, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1;
dds_entity_t publisher;
publisher = dds_get_publisher(entity);
cr_assert_eq(dds_err_nr(publisher), dds_err_nr(exp), "returned %d != expected %d", dds_err_nr(publisher), dds_err_nr(exp));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_publisher, non_writers) = {
DataPoints(dds_entity_t*, &g_publisher, &g_reader, &g_publisher, &g_topic, &g_participant),
};
Theory((dds_entity_t *cond), ddsc_entity_get_publisher, non_writers, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t publisher;
publisher = dds_get_publisher(*cond);
cr_assert_eq(dds_err_nr(publisher), DDS_RETCODE_ILLEGAL_OPERATION, "returned %d", dds_err_nr(publisher));
}
/*************************************************************************************************/
/**************************************************************************************************
*
* These will check the dds_get_subscriber in various ways.
*
*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_subscriber, readers) = {
DataPoints(dds_entity_t*, &g_readcond, &g_querycond, &g_reader),
};
Theory((dds_entity_t *entity), ddsc_entity_get_subscriber, readers, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t subscriber;
subscriber = dds_get_subscriber(*entity);
cr_assert_eq(subscriber, g_subscriber);
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_subscriber, deleted_readers) = {
DataPoints(dds_entity_t*, &g_readcond, &g_querycond, &g_reader),
};
Theory((dds_entity_t *entity), ddsc_entity_get_subscriber, deleted_readers, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t subscriber;
dds_delete(*entity);
subscriber = dds_get_subscriber(*entity);
cr_assert_eq(dds_err_nr(subscriber), DDS_RETCODE_ALREADY_DELETED);
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_subscriber, invalid_readers) = {
DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN),
};
Theory((dds_entity_t entity), ddsc_entity_get_subscriber, invalid_readers, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1;
dds_entity_t subscriber;
subscriber = dds_get_subscriber(entity);
cr_assert_eq(dds_err_nr(subscriber), dds_err_nr(exp), "returned %d != expected %d", dds_err_nr(subscriber), dds_err_nr(exp));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_subscriber, non_readers) = {
DataPoints(dds_entity_t*, &g_subscriber, &g_writer, &g_publisher, &g_topic, &g_participant),
};
Theory((dds_entity_t *cond), ddsc_entity_get_subscriber, non_readers, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t subscriber;
subscriber = dds_get_subscriber(*cond);
cr_assert_eq(dds_err_nr(subscriber), DDS_RETCODE_ILLEGAL_OPERATION, "returned %d", dds_err_nr(subscriber));
}
/*************************************************************************************************/
/**************************************************************************************************
*
* These will check the dds_get_datareader in various ways.
*
*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_datareader, conditions) = {
DataPoints(dds_entity_t*, &g_readcond, &g_querycond),
};
Theory((dds_entity_t *cond), ddsc_entity_get_datareader, conditions, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t reader;
reader = dds_get_datareader(*cond);
cr_assert_eq(reader, g_reader);
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_datareader, deleted_conds) = {
DataPoints(dds_entity_t*, &g_readcond, &g_querycond),
};
Theory((dds_entity_t *cond), ddsc_entity_get_datareader, deleted_conds, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t reader;
dds_delete(*cond);
reader = dds_get_datareader(*cond);
cr_assert_eq(dds_err_nr(reader), DDS_RETCODE_ALREADY_DELETED);
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_datareader, invalid_conds) = {
DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN),
};
Theory((dds_entity_t cond), ddsc_entity_get_datareader, invalid_conds, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1;
dds_entity_t reader;
reader = dds_get_datareader(cond);
cr_assert_eq(dds_err_nr(reader), dds_err_nr(exp), "returned %d != expected %d", dds_err_nr(reader), dds_err_nr(exp));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_entity_get_datareader, non_conds) = {
DataPoints(dds_entity_t*, &g_reader, &g_subscriber, &g_writer, &g_publisher, &g_topic, &g_participant),
};
Theory((dds_entity_t *cond), ddsc_entity_get_datareader, non_conds, .init=hierarchy_init, .fini=hierarchy_fini)
{
dds_entity_t reader;
reader = dds_get_datareader(*cond);
cr_assert_eq(dds_err_nr(reader), DDS_RETCODE_ILLEGAL_OPERATION, "returned %d", dds_err_nr(reader));
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_implicit_publisher, deleted)
{
dds_entity_t participant;
dds_entity_t writer;
dds_entity_t topic;
dds_return_t ret;
char name[100];
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0);
topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_entity_implicit_publisher_test", name, 100), NULL, NULL);
cr_assert_gt(topic, 0);
writer = dds_create_writer(participant, topic, NULL, NULL);
cr_assert_gt(writer, 0);
ret = dds_get_children(participant, NULL, 0);
cr_assert_eq(ret, 2);
dds_delete(writer);
ret = dds_get_children(participant, NULL, 0);
cr_assert_eq(ret, 1);
dds_delete(topic);
dds_delete(participant);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_implicit_publisher, invalid_topic)
{
dds_entity_t participant;
dds_entity_t writer;
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0);
/* Disable SAL warning on intentional misuse of the API */
OS_WARNING_MSVC_OFF(28020);
writer = dds_create_writer(participant, 0, NULL, NULL);
/* Disable SAL warning on intentional misuse of the API */
OS_WARNING_MSVC_ON(28020);
cr_assert_lt(writer, 0);
dds_delete(writer);
dds_delete(participant);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_implicit_subscriber, deleted)
{
dds_entity_t participant;
dds_entity_t reader;
dds_entity_t topic;
dds_return_t ret;
char name[100];
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0);
topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_entity_implicit_subscriber_test", name, 100), NULL, NULL);
cr_assert_gt(topic, 0);
reader = dds_create_reader(participant, topic, NULL, NULL);
cr_assert_gt(reader, 0);
ret = dds_get_children(participant, NULL, 0);
cr_assert_eq(ret, 2);
dds_delete(reader);
ret = dds_get_children(participant, NULL, 0);
cr_assert_eq(ret, 1);
dds_delete(topic);
dds_delete(participant);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_explicit_subscriber, invalid_topic)
{
dds_entity_t participant;
dds_entity_t reader;
dds_entity_t subscriber;
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0);
subscriber = dds_create_subscriber(participant, NULL,NULL);
/* Disable SAL warning on intentional misuse of the API */
OS_WARNING_MSVC_OFF(28020);
reader = dds_create_reader(subscriber, 0, NULL, NULL);
OS_WARNING_MSVC_ON(28020);
cr_assert_lt(reader, 0);
dds_delete(reader);
dds_delete(participant);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_children, implicit_publisher)
{
dds_entity_t participant;
dds_entity_t publisher;
dds_entity_t writer;
dds_entity_t topic;
dds_entity_t child[2], child2[2];
dds_return_t ret;
char name[100];
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0);
topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_entity_implicit_publisher_test", name, 100), NULL, NULL);
cr_assert_gt(topic, 0);
writer = dds_create_writer(participant, topic, NULL, NULL);
cr_assert_gt(writer, 0);
ret = dds_get_children(participant, child, 2);
cr_assert_eq(ret, 2);
if(child[0] == topic){
publisher = child[1];
} else if(child[1] == topic){
publisher = child[0];
} else{
cr_assert(false, "topic was not returned");
}
cr_assert_neq(publisher, topic);
cr_assert_gt(publisher, 0);
cr_assert_neq(publisher, writer);
dds_delete(writer);
ret = dds_get_children(participant, child2, 2);
cr_assert_eq(ret, 2);
cr_assert( (child2[0] == child[0]) || (child2[0] == child[1]) );
cr_assert( (child2[1] == child[0]) || (child2[1] == child[1]) );
dds_delete(topic);
dds_delete(participant);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_children, implicit_subscriber)
{
dds_entity_t participant;
dds_entity_t subscriber;
dds_entity_t reader;
dds_entity_t topic;
dds_entity_t child[2], child2[2];
dds_return_t ret;
char name[100];
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0);
topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_entity_implicit_subscriber_test", name, 100), NULL, NULL);
cr_assert_gt(topic, 0);
reader = dds_create_reader(participant, topic, NULL, NULL);
cr_assert_gt(reader, 0);
ret = dds_get_children(participant, child, 2);
cr_assert_eq(ret, 2);
if(child[0] == topic){
subscriber = child[1];
} else if(child[1] == topic){
subscriber = child[0];
} else{
cr_assert(false, "topic was not returned");
}
cr_assert_neq(subscriber, topic);
cr_assert_gt(subscriber, 0);
cr_assert_neq(subscriber, reader);
dds_delete(reader);
ret = dds_get_children(participant, child2, 2);
cr_assert_eq(ret, 2);
cr_assert( (child2[0] == child[0]) || (child2[0] == child[1]) );
cr_assert( (child2[1] == child[0]) || (child2[1] == child[1]) );
dds_delete(topic);
dds_delete(participant);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_parent, implicit_publisher)
{
dds_entity_t participant;
dds_entity_t writer;
dds_entity_t parent;
dds_entity_t topic;
dds_return_t ret;
char name[100];
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0);
topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_entity_implicit_publisher_promotion_test", name, 100), NULL, NULL);
cr_assert_gt(topic, 0);
writer = dds_create_writer(participant, topic, NULL, NULL);
cr_assert_gt(writer, 0);
parent = dds_get_parent(writer);
cr_assert_neq(parent, participant);
cr_assert_gt(parent, 0);
dds_delete(writer);
ret = dds_delete(parent);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_OK);
dds_delete(participant);
}
/*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_entity_get_parent, implicit_subscriber)
{
dds_entity_t participant;
dds_entity_t reader;
dds_entity_t parent;
dds_entity_t topic;
dds_return_t ret;
char name[100];
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0);
topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, create_topic_name("ddsc_entity_implicit_subscriber_promotion_test", name, 100), NULL, NULL);
cr_assert_gt(topic, 0);
reader = dds_create_reader(participant, topic, NULL, NULL);
cr_assert_gt(reader, 0);
parent = dds_get_parent(reader);
cr_assert_neq(parent, participant);
cr_assert_gt(parent, 0);
dds_delete(reader);
ret = dds_delete(parent);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_OK);
dds_delete(participant);
}
/*************************************************************************************************/
/*************************************************************************************************/
#endif

File diff suppressed because it is too large Load diff

33
src/core/ddsc/tests/err.c Normal file
View file

@ -0,0 +1,33 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "ddsc/dds.h"
#include <criterion/criterion.h>
#include <criterion/logging.h>
Test(ddsc_err, str)
{
cr_assert_str_eq(dds_err_str(1 ), "Success");
cr_assert_str_eq(dds_err_str(-255 ), "Unknown");
cr_assert_str_eq(dds_err_str(DDS_RETCODE_OK * -1), "Success");
cr_assert_str_eq(dds_err_str(DDS_RETCODE_ERROR * -1), "Error");
cr_assert_str_eq(dds_err_str(DDS_RETCODE_UNSUPPORTED * -1), "Unsupported");
cr_assert_str_eq(dds_err_str(DDS_RETCODE_BAD_PARAMETER * -1), "Bad Parameter");
cr_assert_str_eq(dds_err_str(DDS_RETCODE_PRECONDITION_NOT_MET * -1), "Precondition Not Met");
cr_assert_str_eq(dds_err_str(DDS_RETCODE_OUT_OF_RESOURCES * -1), "Out Of Resources");
cr_assert_str_eq(dds_err_str(DDS_RETCODE_NOT_ENABLED * -1), "Not Enabled");
cr_assert_str_eq(dds_err_str(DDS_RETCODE_IMMUTABLE_POLICY * -1), "Immutable Policy");
cr_assert_str_eq(dds_err_str(DDS_RETCODE_INCONSISTENT_POLICY * -1), "Inconsistent Policy");
cr_assert_str_eq(dds_err_str(DDS_RETCODE_ALREADY_DELETED * -1), "Already Deleted");
cr_assert_str_eq(dds_err_str(DDS_RETCODE_TIMEOUT * -1), "Timeout");
cr_assert_str_eq(dds_err_str(DDS_RETCODE_NO_DATA * -1), "No Data");
cr_assert_str_eq(dds_err_str(DDS_RETCODE_ILLEGAL_OPERATION * -1), "Illegal Operation");
}

View file

@ -0,0 +1,39 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "ddsc/dds.h"
#include <criterion/criterion.h>
#include <criterion/logging.h>
#include "os/os.h"
Test(ddsc_err, unique_file_id)
{
dds_entity_t participant, reader, writer;
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0);
/* Disable SAL warning on intentional misuse of the API */
OS_WARNING_MSVC_OFF(28020);
reader = dds_create_reader(0, 0, NULL, NULL);
cr_assert_lt(reader, 0);
writer = dds_create_writer(0, 0, NULL, NULL);
cr_assert_lt(writer, 0);
OS_WARNING_MSVC_ON(28020);
cr_log_info("file_id for dds_create_reader: %d", dds_err_file_id(reader));
cr_log_info("file_id for dds_create_writer: %d", dds_err_file_id(writer));
cr_assert_neq(dds_err_file_id(reader), dds_err_file_id(writer));
dds_delete(participant);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,332 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "ddsc/dds.h"
#include <criterion/criterion.h>
#include <os/os.h>
#include "config_env.h"
#include "ddsc/ddsc_project.h"
#define cr_assert_status_eq(s1, s2, ...) cr_assert_eq(dds_err_nr(s1), s2, __VA_ARGS__)
Test(ddsc_participant, create_and_delete) {
dds_entity_t participant, participant2, participant3;
participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0, "dds_participant_create");
participant2 = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant2, 0, "dds_participant_create");
dds_delete (participant);
dds_delete (participant2);
participant3 = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant3, 0, "dds_participant_create");
dds_delete (participant3);
}
/* Test for creating participant with no configuration file */
Test(ddsc_participant, create_with_no_conf_no_env) {
dds_entity_t participant, participant2, participant3;
dds_return_t status;
dds_domainid_t domain_id;
dds_domainid_t valid_domain=0;
const char * env_uri = os_getenv(DDSC_PROJECT_NAME_NOSPACE_CAPS"_URI");
cr_assert_eq(env_uri, NULL, DDSC_PROJECT_NAME_NOSPACE_CAPS"_URI must be NULL");
//invalid domain
participant = dds_create_participant (1, NULL, NULL);
cr_assert_lt(participant, 0, "Error must be received for invalid domain value");
//valid specific domain value
participant2 = dds_create_participant (valid_domain, NULL, NULL);
cr_assert_gt(participant2, 0, "Valid participant must be received for valid specific domain value");
status = dds_get_domainid(participant2, &domain_id);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_get_domainid(participant, domain_id)");
cr_assert_eq(domain_id, valid_domain, "Retrieved domain ID must be valid");
//DDS_DOMAIN_DEFAULT from user
participant3 = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant3, 0, "Valid participant must be received for DDS_DOMAIN_DEFAULT");
status = dds_get_domainid(participant3, &domain_id);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_get_domainid(participant, domain_id)");
cr_assert_eq(domain_id, valid_domain, "Retrieved domain ID must be valid");
dds_delete(participant2);
dds_delete(participant3);
}
////WITH CONF
/* Test for creating participant with valid configuration file */
Test(ddsc_participant, create_with_conf_no_env) {
dds_entity_t participant, participant2, participant3;
dds_return_t status;
dds_domainid_t domain_id;
dds_domainid_t valid_domain=3;
static char env_uri_str[1000];
(void) sprintf(env_uri_str, "%s=%s", DDSC_PROJECT_NAME_NOSPACE_CAPS"_URI", CONFIG_ENV_SIMPLE_UDP);
os_putenv(env_uri_str);
static char env_mp_str[100];
(void) sprintf(env_mp_str, "%s=%s", "MAX_PARTICIPANTS", CONFIG_ENV_MAX_PARTICIPANTS);
os_putenv(env_mp_str);
const char * env_uri = os_getenv(DDSC_PROJECT_NAME_NOSPACE_CAPS"_URI");
cr_assert_neq(env_uri, NULL, DDSC_PROJECT_NAME_NOSPACE_CAPS"_URI must be set");
//invalid domain
participant = dds_create_participant (1, NULL, NULL);
cr_assert_lt(participant, 0, "Error must be received for invalid domain value");
//valid specific domain value
participant2 = dds_create_participant (valid_domain, NULL, NULL);
cr_assert_gt(participant2, 0, "Valid participant must be received for valid specific domain value");
status = dds_get_domainid(participant2, &domain_id);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_get_domainid(participant, domain_id)");
cr_assert_eq(domain_id, valid_domain, "Retrieved domain ID must be valid");
//DDS_DOMAIN_DEFAULT from the user
participant3 = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant3, 0, "Valid participant must be received for DDS_DOMAIN_DEFAULT");
status = dds_get_domainid(participant3, &domain_id);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_get_domainid(participant, domain_id)");
cr_assert_eq(domain_id, valid_domain, "Retrieved domain ID must be valid");
dds_delete(participant2);
dds_delete(participant3);
}
Test(ddsc_participant_lookup, one) {
dds_entity_t participant;
dds_entity_t participants[3];
dds_domainid_t domain_id;
dds_return_t status, num_of_found_pp;
size_t size = 3;
/* Create a participant */
participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0, "dds_participant_create");
/* Get domain id */
status = dds_get_domainid(participant, &domain_id);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_get_domainid(participant, domain_id)");
num_of_found_pp = dds_lookup_participant( domain_id, participants, size);
cr_assert_eq(num_of_found_pp, 1, "dds_lookup_participant(domain_id, participants, size)");
cr_assert_eq(participants[0], participant,"dds_lookup_participant did not return the participant");
dds_delete (participant);
}
Test(ddsc_participant_lookup, multiple) {
dds_entity_t participant, participant2;
dds_entity_t participants[2];
dds_domainid_t domain_id;
dds_return_t status, num_of_found_pp;
size_t size = 2;
/* Create participants */
participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0, "dds_participant_create");
participant2 = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant2, 0, "dds_participant_create");
/* Get domain id */
status = dds_get_domainid(participant, &domain_id);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_get_domainid(participant, domain_id)");
num_of_found_pp = dds_lookup_participant( domain_id, participants, size);
cr_assert_eq(num_of_found_pp, 2, "dds_lookup_participant(domain_id, participants, size)");
cr_assert(participants[0] == participant || participants[0] == participant2,"ddsc_participant_lookup");
cr_assert(participants[1] == participant || participants[1] == participant2,"ddsc_participant_lookup");
cr_assert_neq(participants[0], participants[1], "dds_lookup_participant returned a participant twice");
dds_delete (participant2);
dds_delete (participant);
}
Test(ddsc_participant_lookup, array_too_small) {
dds_entity_t participant, participant2, participant3;
dds_entity_t participants[2];
dds_domainid_t domain_id;
dds_return_t status, num_of_found_pp;
size_t size = 2;
/* Create participants */
participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0, "dds_participant_create");
participant2 = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant2, 0, "dds_participant_create");
participant3 = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant3, 0, "dds_participant_create");
/* Get domain id */
status = dds_get_domainid(participant, &domain_id);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_get_domainid(participant, domain_id)");
num_of_found_pp = dds_lookup_participant( domain_id, participants, size);
cr_assert_eq(num_of_found_pp, 3, "dds_lookup_participant(domain_id, participants, size)");
cr_assert(participants[0] == participant || participants[0] == participant2 || participants[0] == participant3,"ddsc_participant_lookup");
cr_assert(participants[1] == participant || participants[1] == participant2 || participants[1] == participant3,"ddsc_participant_lookup");
cr_assert_neq(participants[0], participants[1], "dds_lookup_participant returned a participant twice");
dds_delete (participant3);
dds_delete (participant2);
dds_delete (participant);
}
Test(ddsc_participant_lookup, null_zero){
dds_entity_t participant;
dds_domainid_t domain_id;
dds_return_t status, num_of_found_pp;
size_t size = 0;
/* Create a participant */
participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0, "dds_participant_create");
/* Get domain id */
status = dds_get_domainid(participant, &domain_id);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_get_domainid(participant, domain_id)");
num_of_found_pp = dds_lookup_participant( domain_id, NULL, size);
cr_assert_eq(num_of_found_pp, 1, "dds_lookup_participant(domain_id, participants, size)");
dds_delete (participant);
}
Test(ddsc_participant_lookup, null_nonzero){
dds_entity_t participant;
dds_domainid_t domain_id;
dds_return_t status, num_of_found_pp;
size_t size = 2;
/* Create a participant */
participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0, "dds_participant_create");
/* Get domain id */
status = dds_get_domainid(participant, &domain_id);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_get_domainid(participant, domain_id)");
num_of_found_pp = dds_lookup_participant( domain_id, NULL, size);
cr_assert_status_eq(num_of_found_pp, DDS_RETCODE_BAD_PARAMETER, "dds_lookup_participant did not return bad parameter");
dds_delete (participant);
}
Test(ddsc_participant_lookup, unknown_id) {
dds_entity_t participant;
dds_entity_t participants[3];
dds_domainid_t domain_id;
dds_return_t status, num_of_found_pp;
size_t size = 3;
/* Create a participant */
participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0, "dds_participant_create");
/* Get domain id */
status = dds_get_domainid(participant, &domain_id);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_get_domainid(participant, domain_id)");
domain_id ++;
num_of_found_pp = dds_lookup_participant( domain_id, participants, size);
cr_assert_eq(num_of_found_pp, 0, "dds_lookup_participant(domain_id, participants, size)");
dds_delete (participant);
}
Test(ddsc_participant_lookup, none) {
dds_entity_t participants[2];
dds_return_t num_of_found_pp;
size_t size = 2;
num_of_found_pp = dds_lookup_participant( 0, participants, size);
cr_assert_eq(num_of_found_pp, 0, "dds_lookup_participant did not return 0");
}
Test(ddsc_participant_lookup, no_more) {
dds_entity_t participant;
dds_entity_t participants[3];
dds_domainid_t domain_id;
dds_return_t status, num_of_found_pp;
size_t size = 3;
/* Create a participant */
participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0, "dds_participant_create");
/* Get domain id */
status = dds_get_domainid(participant, &domain_id);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_get_domainid(participant, domain_id)");
dds_delete (participant);
num_of_found_pp = dds_lookup_participant( domain_id, participants, size);
cr_assert_eq(num_of_found_pp, 0, "dds_lookup_participant did not return 0");
}
Test(ddsc_participant_lookup, deleted) {
dds_entity_t participant, participant2;
dds_entity_t participants[2];
dds_domainid_t domain_id;
dds_return_t status, num_of_found_pp;
size_t size = 2;
/* Create participants */
participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0, "dds_participant_create");
participant2 = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant2, 0, "dds_participant_create");
/* Get domain id */
status = dds_get_domainid(participant, &domain_id);
cr_assert_status_eq(status, DDS_RETCODE_OK, "dds_get_domainid(participant, domain_id)");
dds_delete (participant2);
num_of_found_pp = dds_lookup_participant( domain_id, participants, size);
cr_assert_eq(num_of_found_pp, 1, "dds_lookup_participant did not return one participant");
cr_assert(participants[0] == participant,"ddsc_participant_lookup");
dds_delete (participant);
}

View file

@ -0,0 +1,268 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "ddsc/dds.h"
#include <criterion/criterion.h>
#include <criterion/logging.h>
/* We are deliberately testing some bad arguments that SAL will complain about.
* So, silence SAL regarding these issues. */
#pragma warning(push)
#pragma warning(disable: 28020)
#define cr_assert_status_eq(s1, s2, ...) cr_assert_eq(dds_err_nr(s1), s2, __VA_ARGS__)
/* Dummy callback */
static void data_available_cb(dds_entity_t reader, void* arg) {}
Test(ddsc_publisher, create)
{
const char *singlePartitions[] = { "partition" };
const char *multiplePartitions[] = { "partition1", "partition2" };
const char *duplicatePartitions[] = { "partition", "partition" };
dds_entity_t participant;
dds_entity_t publisher, publisher1;
dds_listener_t *listener;
dds_qos_t *qos;
/* Use NULL participant */
publisher = dds_create_publisher(0, NULL, NULL);
cr_assert_eq(dds_err_nr(publisher), DDS_RETCODE_BAD_PARAMETER, "dds_create_publisher(NULL,NULL,NULL)");
participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0, "dds_create_participant(DDS_DOMAIN_DEFAULT,NULL,NULL)");
/* Use non-null participant */
publisher = dds_create_publisher(participant, NULL, NULL);
cr_assert_gt(publisher, 0, "dds_create_publisher(participant,NULL,NULL)");
/* Use entity that is not a participant */
publisher1 = dds_create_publisher(publisher, NULL, NULL);
cr_assert_eq(dds_err_nr(publisher1), DDS_RETCODE_ILLEGAL_OPERATION, "dds_create_publisher(publisher,NULL,NULL)");
dds_delete(publisher);
/* Create a non-null qos */
qos = dds_qos_create();
cr_assert_neq(qos, NULL, "dds_qos_create()");
/* Use qos without partition; in that case the default partition should be used */
publisher = dds_create_publisher(participant, qos, NULL);
cr_assert_gt(publisher, 0, "dds_create_publisher(participant,qos,NULL) where qos with default partition");
dds_delete(publisher);
/* Somehow, the compiler thinks the char arrays might not be zero-terminated... */
#pragma warning(push)
#pragma warning(disable: 6054)
/* Use qos with single partition */
dds_qset_partition (qos, 1, singlePartitions);
publisher = dds_create_publisher(participant, qos, NULL);
cr_assert_gt(publisher, 0, "dds_create_publisher(participant,qos,NULL) where qos with single partition");
dds_delete(publisher);
/* Use qos with multiple partitions */
dds_qset_partition (qos, 2, multiplePartitions);
publisher = dds_create_publisher(participant, qos, NULL);
cr_assert_gt(publisher, 0, "dds_create_publisher(participant,qos,NULL) where qos with multiple partitions");
dds_delete(publisher);
/* Use qos with multiple partitions */
dds_qset_partition (qos, 2, duplicatePartitions);
publisher = dds_create_publisher(participant, qos, NULL);
cr_assert_gt(publisher, 0, "dds_create_publisher(participant,qos,NULL) where qos with duplicate partitions");
dds_delete(publisher);
#pragma warning(pop)
/* Use listener(NULL) */
listener = dds_listener_create(NULL);
cr_assert_neq(listener, NULL, "dds_listener_create(NULL)");
publisher = dds_create_publisher(participant, NULL, listener);
cr_assert_gt(publisher, 0, "dds_create_publisher(participant,NULL,listener(NULL))");
dds_delete(publisher);
dds_listener_reset(listener);
/* Use listener for data_available */
dds_lset_data_available(listener, NULL);
publisher = dds_create_publisher(participant, NULL, listener);
cr_assert_gt(publisher, 0, "dds_create_publisher(participant,NULL,listener) with dds_lset_data_available(listener, NULL)");
dds_delete(publisher);
dds_listener_reset(listener);
/* Use DDS_LUNSET for data_available */
dds_lset_data_available(listener, DDS_LUNSET);
publisher = dds_create_publisher(participant, NULL, listener);
cr_assert_gt(publisher, 0, "dds_create_publisher(participant,NULL,listener) with dds_lset_data_available(listener, DDS_LUNSET)");
dds_delete(publisher);
dds_listener_reset(listener);
/* Use callback for data_available */
dds_lset_data_available(listener, data_available_cb);
publisher = dds_create_publisher(participant, NULL, listener);
cr_assert_gt(publisher, 0, "dds_create_publisher(participant,NULL,listener) with dds_lset_data_available(listener, data_available_cb)");
dds_delete(publisher);
/* Use both qos setting and callback listener */
dds_lset_data_available(listener, data_available_cb);
publisher = dds_create_publisher(participant, qos, listener);
cr_assert_gt(publisher, 0, "dds_create_publisher(participant,qos,listener) with dds_lset_data_available(listener, data_available_cb)");
dds_delete(publisher);
dds_listener_delete(listener);
dds_qos_delete(qos);
dds_delete (participant);
}
Test(ddsc_publisher, suspend_resume)
{
dds_entity_t participant, publisher;
dds_return_t status;
/* Suspend a 0 publisher */
status = dds_suspend(0);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_suspend(NULL)");
/* Resume a 0 publisher */
status = dds_resume(0);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_resume(NULL)");
/* Uae dds_suspend on something else than a publisher */
participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0, "dds_create_participant(DDS_DOMAIN_DEFAULT,NULL,NULL)");
status = dds_suspend(participant);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_suspend(participant)");
/* Use dds_resume on something else than a publisher */
status = dds_resume(participant);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_resume(participant)");
/* Use dds_resume without calling dds_suspend */
publisher = dds_create_publisher(participant, NULL, NULL);
cr_assert_gt(publisher, 0, "dds_create_publisher(participant,NULL,NULL)");
status = dds_resume(publisher); /* Should be precondition not met? */
cr_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED, "dds_resume(publisher) without prior suspend");
/* Use dds_suspend on non-null publisher */
status = dds_suspend(publisher);
cr_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED, "dds_suspend(publisher)");
/* Use dds_resume on non-null publisher */
status = dds_resume(publisher);
cr_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED, "dds_resume(publisher)");
dds_delete(publisher);
dds_delete(participant);
return;
}
Test(ddsc_publisher, wait_for_acks)
{
dds_entity_t participant, publisher;
dds_return_t status;
dds_duration_t zeroSec = ((dds_duration_t)DDS_SECS(0));
dds_duration_t oneSec = ((dds_duration_t)DDS_SECS(1));
dds_duration_t minusOneSec = ((dds_duration_t)DDS_SECS(-1));
/* Wait_for_acks on 0 publisher or writer and minusOneSec timeout */
status = dds_wait_for_acks(0, minusOneSec);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_wait_for_acks(NULL,-1)");
/* Wait_for_acks on NULL publisher or writer and zeroSec timeout */
status = dds_wait_for_acks(0, zeroSec);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_wait_for_acks(NULL,0)");
/* wait_for_acks on NULL publisher or writer and oneSec timeout */
status = dds_wait_for_acks(0, oneSec);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_wait_for_acks(NULL,1)");
/* wait_for_acks on NULL publisher or writer and DDS_INFINITE timeout */
status = dds_wait_for_acks(0, DDS_INFINITY);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_wait_for_acks(NULL,DDS_INFINITY)");
participant = dds_create_participant (DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0, "dds_create_participant(DDS_DOMAIN_DEFAULT,NULL,NULL)");
/* Wait_for_acks on participant and minusOneSec timeout */
status = dds_wait_for_acks(participant, minusOneSec);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_wait_for_acks(participant,-1)");
/* Wait_for_acks on participant and zeroSec timeout */
status = dds_wait_for_acks(participant, zeroSec);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_wait_for_acks(participant,0)");
/* Wait_for_acks on participant and oneSec timeout */
status = dds_wait_for_acks(participant, oneSec);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_wait_for_acks(participant,1)");
/* Wait_for_acks on participant and DDS_INFINITE timeout */
status = dds_wait_for_acks(participant, DDS_INFINITY);
cr_assert_status_eq(status, DDS_RETCODE_BAD_PARAMETER, "dds_wait_for_acks(participant,DDS_INFINITY)");
publisher = dds_create_publisher(participant, NULL, NULL);
cr_assert_gt(publisher, 0, "dds_create_publisher(participant,NULL,NULL)");
/* Wait_for_acks on publisher and minusOneSec timeout */
status = dds_wait_for_acks(publisher, minusOneSec);
cr_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED, "dds_wait_for_acks(publisher,-1)");
/* Wait_for_acks on publisher and zeroSec timeout */
status = dds_wait_for_acks(publisher, zeroSec);
cr_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED, "dds_wait_for_acks(publisher,0)");
/* Wait_for_acks on publisher and oneSec timeout */
status = dds_wait_for_acks(publisher, oneSec);
cr_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED, "dds_wait_for_acks(publisher,1)");
/* Wait_for_acks on publisher and DDS_INFINITE timeout */
status = dds_wait_for_acks(publisher, DDS_INFINITY);
cr_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED, "dds_wait_for_acks(publisher,DDS_INFINITY)");
/* TODO: create tests by calling dds_qwait_for_acks on writers */
status = dds_suspend(publisher);
cr_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED, "dds_suspend(publisher)");
/* Wait_for_acks on suspended publisher and minusOneSec timeout */
status = dds_wait_for_acks(publisher, minusOneSec);
cr_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED, "dds_wait_for_acks(suspended_publisher,-1)");
/* Wait_for_acks on suspended publisher and zeroSec timeout */
status = dds_wait_for_acks(publisher, zeroSec);
cr_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED, "dds_wait_for_acks(suspended_publisher,0)");
/* Wait_for_acks on suspended publisher and oneSec timeout */
status = dds_wait_for_acks(publisher, oneSec);
cr_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED, "dds_wait_for_acks(suspended_publisher,1)");
/* Wait_for_acks on suspended publisher and DDS_INFINITE timeout */
status = dds_wait_for_acks(publisher, DDS_INFINITY);
cr_assert_status_eq(status, DDS_RETCODE_UNSUPPORTED, "dds_wait_for_acks(suspended_publisher,DDS_INFINITY)");
dds_delete(publisher);
dds_delete(participant);
return;
}
Test(ddsc_publisher, coherency)
{
return;
}
#pragma warning(pop)

621
src/core/ddsc/tests/qos.c Normal file
View file

@ -0,0 +1,621 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "ddsc/dds.h"
#include "os/os.h"
#include <criterion/criterion.h>
#include <criterion/logging.h>
#if 0
#else
/* We are deliberately testing some bad arguments that SAL will complain about.
* So, silence SAL regarding these issues. */
#pragma warning(push)
#pragma warning(disable: 6387 28020)
/****************************************************************************
* Convenience global policies
****************************************************************************/
struct pol_userdata {
void *value;
size_t sz;
};
struct pol_topicdata {
void *value;
size_t sz;
};
struct pol_groupdata {
void *value;
size_t sz;
};
struct pol_durability {
dds_durability_kind_t kind;
};
struct pol_history {
dds_history_kind_t kind;
int32_t depth;
};
struct pol_resource_limits {
int32_t max_samples;
int32_t max_instances;
int32_t max_samples_per_instance;
};
struct pol_presentation {
dds_presentation_access_scope_kind_t access_scope;
bool coherent_access;
bool ordered_access;
};
struct pol_lifespan {
dds_duration_t lifespan;
};
struct pol_deadline {
dds_duration_t deadline;
};
struct pol_latency_budget {
dds_duration_t duration;
};
struct pol_ownership {
dds_ownership_kind_t kind;
};
struct pol_ownership_strength {
int32_t value;
};
struct pol_liveliness {
dds_liveliness_kind_t kind;
dds_duration_t lease_duration;
};
struct pol_time_based_filter {
dds_duration_t minimum_separation;
};
struct pol_partition {
uint32_t n;
char **ps;
};
struct pol_reliability {
dds_reliability_kind_t kind;
dds_duration_t max_blocking_time;
};
struct pol_transport_priority {
int32_t value;
};
struct pol_destination_order {
dds_destination_order_kind_t kind;
};
struct pol_writer_data_lifecycle {
bool autodispose;
};
struct pol_reader_data_lifecycle {
dds_duration_t autopurge_nowriter_samples_delay;
dds_duration_t autopurge_disposed_samples_delay;
};
struct pol_durability_service {
dds_duration_t service_cleanup_delay;
dds_history_kind_t history_kind;
int32_t history_depth;
int32_t max_samples;
int32_t max_instances;
int32_t max_samples_per_instance;
};
static struct pol_userdata g_pol_userdata;
static struct pol_topicdata g_pol_topicdata;
static struct pol_groupdata g_pol_groupdata;
static struct pol_durability g_pol_durability;
static struct pol_history g_pol_history;
static struct pol_resource_limits g_pol_resource_limits;
static struct pol_presentation g_pol_presentation;
static struct pol_lifespan g_pol_lifespan;
static struct pol_deadline g_pol_deadline;
static struct pol_latency_budget g_pol_latency_budget;
static struct pol_ownership g_pol_ownership;
static struct pol_ownership_strength g_pol_ownership_strength;
static struct pol_liveliness g_pol_liveliness;
static struct pol_time_based_filter g_pol_time_based_filter;
static struct pol_partition g_pol_partition;
static struct pol_reliability g_pol_reliability;
static struct pol_transport_priority g_pol_transport_priority;
static struct pol_destination_order g_pol_destination_order;
static struct pol_writer_data_lifecycle g_pol_writer_data_lifecycle;
static struct pol_reader_data_lifecycle g_pol_reader_data_lifecycle;
static struct pol_durability_service g_pol_durability_service;
static const char* c_userdata = "user_key";
static const char* c_topicdata = "topic_key";
static const char* c_groupdata = "group_key";
static const char* c_partitions[] = {"Partition1", "Partition2"};
/****************************************************************************
* Test initializations and teardowns.
****************************************************************************/
static dds_qos_t *g_qos = NULL;
static void
qos_init(void)
{
g_qos = dds_qos_create();
cr_assert_not_null(g_qos);
g_pol_userdata.value = (void*)c_userdata;
g_pol_userdata.sz = strlen((char*)g_pol_userdata.value) + 1;
g_pol_topicdata.value = (void*)c_topicdata;
g_pol_topicdata.sz = strlen((char*)g_pol_topicdata.value) + 1;
g_pol_groupdata.value = (void*)c_groupdata;
g_pol_groupdata.sz = strlen((char*)g_pol_groupdata.value) + 1;
g_pol_durability.kind = DDS_DURABILITY_TRANSIENT;
g_pol_history.kind = DDS_HISTORY_KEEP_LAST;
g_pol_history.depth = 1;
g_pol_resource_limits.max_samples = 1;
g_pol_resource_limits.max_instances = 1;
g_pol_resource_limits.max_samples_per_instance = 1;
g_pol_presentation.access_scope = DDS_PRESENTATION_INSTANCE;
g_pol_presentation.coherent_access = true;
g_pol_presentation.ordered_access = true;
g_pol_lifespan.lifespan = 10000;
g_pol_deadline.deadline = 20000;
g_pol_latency_budget.duration = 30000;
g_pol_ownership.kind = DDS_OWNERSHIP_EXCLUSIVE;
g_pol_ownership_strength.value = 10;
g_pol_liveliness.kind = DDS_LIVELINESS_AUTOMATIC;
g_pol_liveliness.lease_duration = 40000;
g_pol_time_based_filter.minimum_separation = 50000;
g_pol_partition.ps = (char**)c_partitions;
g_pol_partition.n = 2;
g_pol_reliability.kind = DDS_RELIABILITY_RELIABLE;
g_pol_reliability.max_blocking_time = 60000;
g_pol_transport_priority.value = 42;
g_pol_destination_order.kind = DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP;
g_pol_writer_data_lifecycle.autodispose = true;
g_pol_reader_data_lifecycle.autopurge_disposed_samples_delay = 70000;
g_pol_reader_data_lifecycle.autopurge_nowriter_samples_delay = 80000;
g_pol_durability_service.history_depth = 1;
g_pol_durability_service.history_kind = DDS_HISTORY_KEEP_LAST;
g_pol_durability_service.max_samples = 2;
g_pol_durability_service.max_instances = 3;
g_pol_durability_service.max_samples_per_instance = 4;
g_pol_durability_service.service_cleanup_delay = 90000;
}
static void
qos_fini(void)
{
dds_qos_delete(g_qos);
}
/****************************************************************************
* API tests
****************************************************************************/
Test(ddsc_qos, userdata, .init=qos_init, .fini=qos_fini)
{
struct pol_userdata p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_userdata(NULL, g_pol_userdata.value, g_pol_userdata.sz);
dds_qget_userdata(NULL, &p.value, &p.sz);
dds_qget_userdata(g_qos, NULL, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_userdata(g_qos, g_pol_userdata.value, g_pol_userdata.sz);
dds_qget_userdata(g_qos, &p.value, &p.sz);
cr_assert_eq(p.sz, g_pol_userdata.sz);
cr_assert_str_eq(p.value, g_pol_userdata.value);
dds_free(p.value);
}
Test(ddsc_qos, topicdata, .init=qos_init, .fini=qos_fini)
{
struct pol_topicdata p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_topicdata(NULL, g_pol_topicdata.value, g_pol_topicdata.sz);
dds_qget_topicdata(NULL, &p.value, &p.sz);
dds_qget_topicdata(g_qos, NULL, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_topicdata(g_qos, g_pol_topicdata.value, g_pol_topicdata.sz);
dds_qget_topicdata(g_qos, &p.value, &p.sz);
cr_assert_eq(p.sz, g_pol_topicdata.sz);
cr_assert_str_eq(p.value, g_pol_topicdata.value);
dds_free(p.value);
}
Test(ddsc_qos, groupdata, .init=qos_init, .fini=qos_fini)
{
struct pol_groupdata p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_groupdata(NULL, g_pol_groupdata.value, g_pol_groupdata.sz);
dds_qget_groupdata(NULL, &p.value, &p.sz);
dds_qget_groupdata(g_qos, NULL, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_groupdata(g_qos, g_pol_groupdata.value, g_pol_groupdata.sz);
dds_qget_groupdata(g_qos, &p.value, &p.sz);
cr_assert_eq(p.sz, g_pol_groupdata.sz);
cr_assert_str_eq(p.value, g_pol_groupdata.value);
dds_free(p.value);
}
Test(ddsc_qos, durability, .init=qos_init, .fini=qos_fini)
{
struct pol_durability p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_durability(NULL, g_pol_durability.kind);
dds_qget_durability(NULL, &p.kind);
dds_qget_durability(g_qos, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_durability(g_qos, g_pol_durability.kind);
dds_qget_durability(g_qos, &p.kind);
cr_assert_eq(p.kind, g_pol_durability.kind);
}
Test(ddsc_qos, history, .init=qos_init, .fini=qos_fini)
{
struct pol_history p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_history(NULL, g_pol_history.kind, g_pol_history.depth);
dds_qget_history(NULL, &p.kind, &p.depth);
dds_qget_history(g_qos, NULL, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_history(g_qos, g_pol_history.kind, g_pol_history.depth);
dds_qget_history(g_qos, &p.kind, &p.depth);
cr_assert_eq(p.kind, g_pol_history.kind);
cr_assert_eq(p.depth, g_pol_history.depth);
}
Test(ddsc_qos, resource_limits, .init=qos_init, .fini=qos_fini)
{
struct pol_resource_limits p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_resource_limits(NULL, g_pol_resource_limits.max_samples, g_pol_resource_limits.max_instances, g_pol_resource_limits.max_samples_per_instance);
dds_qget_resource_limits(NULL, &p.max_samples, &p.max_instances, &p.max_samples_per_instance);
dds_qget_resource_limits(g_qos, NULL, NULL, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_resource_limits(g_qos, g_pol_resource_limits.max_samples, g_pol_resource_limits.max_instances, g_pol_resource_limits.max_samples_per_instance);
dds_qget_resource_limits(g_qos, &p.max_samples, &p.max_instances, &p.max_samples_per_instance);
cr_assert_eq(p.max_samples, g_pol_resource_limits.max_samples);
cr_assert_eq(p.max_instances, g_pol_resource_limits.max_instances);
cr_assert_eq(p.max_samples_per_instance, g_pol_resource_limits.max_samples_per_instance);
}
Test(ddsc_qos, presentation, .init=qos_init, .fini=qos_fini)
{
struct pol_presentation p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_presentation(NULL, g_pol_presentation.access_scope, g_pol_presentation.coherent_access, g_pol_presentation.ordered_access);
dds_qget_presentation(NULL, &p.access_scope, &p.coherent_access, &p.ordered_access);
dds_qget_presentation(g_qos, NULL, NULL, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_presentation(g_qos, g_pol_presentation.access_scope, g_pol_presentation.coherent_access, g_pol_presentation.ordered_access);
dds_qget_presentation(g_qos, &p.access_scope, &p.coherent_access, &p.ordered_access);
cr_assert_eq(p.access_scope, g_pol_presentation.access_scope);
cr_assert_eq(p.coherent_access, g_pol_presentation.coherent_access);
cr_assert_eq(p.ordered_access, g_pol_presentation.ordered_access);
}
Test(ddsc_qos, lifespan, .init=qos_init, .fini=qos_fini)
{
struct pol_lifespan p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_lifespan(NULL, g_pol_lifespan.lifespan);
dds_qget_lifespan(NULL, &p.lifespan);
dds_qget_lifespan(g_qos, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_lifespan(g_qos, g_pol_lifespan.lifespan);
dds_qget_lifespan(g_qos, &p.lifespan);
cr_assert_eq(p.lifespan, g_pol_lifespan.lifespan);
}
Test(ddsc_qos, deadline, .init=qos_init, .fini=qos_fini)
{
struct pol_deadline p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_deadline(NULL, g_pol_deadline.deadline);
dds_qget_deadline(NULL, &p.deadline);
dds_qget_deadline(g_qos, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_deadline(g_qos, g_pol_deadline.deadline);
dds_qget_deadline(g_qos, &p.deadline);
cr_assert_eq(p.deadline, g_pol_deadline.deadline);
}
Test(ddsc_qos, latency_budget, .init=qos_init, .fini=qos_fini)
{
struct pol_latency_budget p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_latency_budget(NULL, g_pol_latency_budget.duration);
dds_qget_latency_budget(NULL, &p.duration);
dds_qget_latency_budget(g_qos, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_latency_budget(g_qos, g_pol_latency_budget.duration);
dds_qget_latency_budget(g_qos, &p.duration);
cr_assert_eq(p.duration, g_pol_latency_budget.duration);
}
Test(ddsc_qos, ownership, .init=qos_init, .fini=qos_fini)
{
struct pol_ownership p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_ownership(NULL, g_pol_ownership.kind);
dds_qget_ownership(NULL, &p.kind);
dds_qget_ownership(g_qos, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_ownership(g_qos, g_pol_ownership.kind);
dds_qget_ownership(g_qos, &p.kind);
cr_assert_eq(p.kind, g_pol_ownership.kind);
}
Test(ddsc_qos, ownership_strength, .init=qos_init, .fini=qos_fini)
{
struct pol_ownership_strength p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_ownership_strength(NULL, g_pol_ownership_strength.value);
dds_qget_ownership_strength(NULL, &p.value);
dds_qget_ownership_strength(g_qos, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_ownership_strength(g_qos, g_pol_ownership_strength.value);
dds_qget_ownership_strength(g_qos, &p.value);
cr_assert_eq(p.value, g_pol_ownership_strength.value);
}
Test(ddsc_qos, liveliness, .init=qos_init, .fini=qos_fini)
{
struct pol_liveliness p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_liveliness(NULL, g_pol_liveliness.kind, g_pol_liveliness.lease_duration);
dds_qget_liveliness(NULL, &p.kind, &p.lease_duration);
dds_qget_liveliness(g_qos, NULL, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_liveliness(g_qos, g_pol_liveliness.kind, g_pol_liveliness.lease_duration);
dds_qget_liveliness(g_qos, &p.kind, &p.lease_duration);
cr_assert_eq(p.kind, g_pol_liveliness.kind);
cr_assert_eq(p.lease_duration, g_pol_liveliness.lease_duration);
}
Test(ddsc_qos, time_base_filter, .init=qos_init, .fini=qos_fini)
{
struct pol_time_based_filter p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_time_based_filter(NULL, g_pol_time_based_filter.minimum_separation);
dds_qget_time_based_filter(NULL, &p.minimum_separation);
dds_qget_time_based_filter(g_qos, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_time_based_filter(g_qos, g_pol_time_based_filter.minimum_separation);
dds_qget_time_based_filter(g_qos, &p.minimum_separation);
cr_assert_eq(p.minimum_separation, g_pol_time_based_filter.minimum_separation);
}
Test(ddsc_qos, partition, .init=qos_init, .fini=qos_fini)
{
struct pol_partition p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_partition(NULL, g_pol_partition.n, c_partitions);
dds_qget_partition(NULL, &p.n, &p.ps);
dds_qget_partition(g_qos, NULL, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_partition(g_qos, g_pol_partition.n, c_partitions);
dds_qget_partition(g_qos, &p.n, &p.ps);
cr_assert_eq(p.n, 2);
cr_assert_eq(p.n, g_pol_partition.n);
cr_assert_str_eq(p.ps[0], g_pol_partition.ps[0]);
cr_assert_str_eq(p.ps[1], g_pol_partition.ps[1]);
dds_free(p.ps[0]);
dds_free(p.ps[1]);
dds_free(p.ps);
}
Test(ddsc_qos, reliability, .init=qos_init, .fini=qos_fini)
{
struct pol_reliability p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_reliability(NULL, g_pol_reliability.kind, g_pol_reliability.max_blocking_time);
dds_qget_reliability(NULL, &p.kind, &p.max_blocking_time);
dds_qget_reliability(g_qos, NULL, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_reliability(g_qos, g_pol_reliability.kind, g_pol_reliability.max_blocking_time);
dds_qget_reliability(g_qos, &p.kind, &p.max_blocking_time);
cr_assert_eq(p.kind, g_pol_reliability.kind);
cr_assert_eq(p.max_blocking_time, g_pol_reliability.max_blocking_time);
}
Test(ddsc_qos, transport_priority, .init=qos_init, .fini=qos_fini)
{
struct pol_transport_priority p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_transport_priority(NULL, g_pol_transport_priority.value);
dds_qget_transport_priority(NULL, &p.value);
dds_qget_transport_priority(g_qos, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_transport_priority(g_qos, g_pol_transport_priority.value);
dds_qget_transport_priority(g_qos, &p.value);
cr_assert_eq(p.value, g_pol_transport_priority.value);
}
Test(ddsc_qos, destination_order, .init=qos_init, .fini=qos_fini)
{
struct pol_destination_order p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_destination_order(NULL, g_pol_destination_order.kind);
dds_qget_destination_order(NULL, &p.kind);
dds_qget_destination_order(g_qos, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_destination_order(g_qos, g_pol_destination_order.kind);
dds_qget_destination_order(g_qos, &p.kind);
cr_assert_eq(p.kind, g_pol_destination_order.kind);
}
Test(ddsc_qos, writer_data_lifecycle, .init=qos_init, .fini=qos_fini)
{
struct pol_writer_data_lifecycle p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_writer_data_lifecycle(NULL, g_pol_writer_data_lifecycle.autodispose);
dds_qget_writer_data_lifecycle(NULL, &p.autodispose);
dds_qget_writer_data_lifecycle(g_qos, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_writer_data_lifecycle(g_qos, g_pol_writer_data_lifecycle.autodispose);
dds_qget_writer_data_lifecycle(g_qos, &p.autodispose);
cr_assert_eq(p.autodispose, g_pol_writer_data_lifecycle.autodispose);
}
Test(ddsc_qos, reader_data_lifecycle, .init=qos_init, .fini=qos_fini)
{
struct pol_reader_data_lifecycle p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_reader_data_lifecycle(NULL, g_pol_reader_data_lifecycle.autopurge_nowriter_samples_delay, g_pol_reader_data_lifecycle.autopurge_disposed_samples_delay);
dds_qget_reader_data_lifecycle(NULL, &p.autopurge_nowriter_samples_delay, &p.autopurge_disposed_samples_delay);
dds_qget_reader_data_lifecycle(g_qos, NULL, NULL);
/* Getting after setting, should yield the original input. */
dds_qset_reader_data_lifecycle(g_qos, g_pol_reader_data_lifecycle.autopurge_nowriter_samples_delay, g_pol_reader_data_lifecycle.autopurge_disposed_samples_delay);
dds_qget_reader_data_lifecycle(g_qos, &p.autopurge_nowriter_samples_delay, &p.autopurge_disposed_samples_delay);
cr_assert_eq(p.autopurge_nowriter_samples_delay, g_pol_reader_data_lifecycle.autopurge_nowriter_samples_delay);
cr_assert_eq(p.autopurge_disposed_samples_delay, g_pol_reader_data_lifecycle.autopurge_disposed_samples_delay);
}
Test(ddsc_qos, durability_service, .init=qos_init, .fini=qos_fini)
{
struct pol_durability_service p = { 0 };
/* NULLs shouldn't crash and be a noops. */
dds_qset_durability_service(NULL,
g_pol_durability_service.service_cleanup_delay,
g_pol_durability_service.history_kind,
g_pol_durability_service.history_depth,
g_pol_durability_service.max_samples,
g_pol_durability_service.max_instances,
g_pol_durability_service.max_samples_per_instance);
dds_qget_durability_service(NULL,
&p.service_cleanup_delay,
&p.history_kind,
&p.history_depth,
&p.max_samples,
&p.max_instances,
&p.max_samples_per_instance);
dds_qget_durability_service(g_qos,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL);
/* Getting after setting, should yield the original input. */
dds_qset_durability_service(g_qos,
g_pol_durability_service.service_cleanup_delay,
g_pol_durability_service.history_kind,
g_pol_durability_service.history_depth,
g_pol_durability_service.max_samples,
g_pol_durability_service.max_instances,
g_pol_durability_service.max_samples_per_instance);
dds_qget_durability_service(g_qos,
&p.service_cleanup_delay,
&p.history_kind,
&p.history_depth,
&p.max_samples,
&p.max_instances,
&p.max_samples_per_instance);
cr_assert_eq(p.service_cleanup_delay, g_pol_durability_service.service_cleanup_delay);
cr_assert_eq(p.history_kind, g_pol_durability_service.history_kind);
cr_assert_eq(p.history_depth, g_pol_durability_service.history_depth);
cr_assert_eq(p.max_samples, g_pol_durability_service.max_samples);
cr_assert_eq(p.max_instances, g_pol_durability_service.max_instances);
cr_assert_eq(p.max_samples_per_instance, g_pol_durability_service.max_samples_per_instance);
}
#endif
#pragma warning(pop)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

3208
src/core/ddsc/tests/reader.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,769 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include "ddsc/dds.h"
#include "os/os.h"
#include "Space.h"
#include "RoundTrip.h"
#include <criterion/criterion.h>
#include <criterion/logging.h>
#include <criterion/theories.h>
#if 0
#define PRINT_SAMPLE(info, sample) cr_log_info("%s (%d, %d, %d)\n", info, sample.long_1, sample.long_2, sample.long_3);
#else
#define PRINT_SAMPLE(info, sample)
#endif
/**************************************************************************************************
*
* Test fixtures
*
*************************************************************************************************/
/*
* By writing, disposing, unregistering, reading and re-writing, the following
* data will be available in the reader history (but not in this order).
* | long_1 | long_2 | long_3 | sst | vst | ist |
* ----------------------------------------------------------
* | 0 | 0 | 0 | not_read | new | alive |
* | 0 | 1 | 2 | not_read | new | alive |
* | 0 | 2 | 4 | not_read | new | alive |
* | 1 | 3 | 6 | read | old | alive |
* | 1 | 4 | 8 | read | old | alive |
* | 1 | 5 | 10 | read | old | alive |
* | 2 | 6 | 12 | not_read | old | alive |
* | 2 | 7 | 14 | not_read | old | alive |
* | 2 | 8 | 16 | read | old | alive |
* | 3 | 9 | 18 | not_read | old | alive |
* | 3 | 10 | 20 | read | old | alive |
* | 3 | 11 | 22 | not_read | old | alive |
* | 4 | 12 | 24 | read | old | alive |
* | 4 | 13 | 26 | not_read | old | alive |
* | 4 | 14 | 28 | not_read | old | alive |
* | 5 | 15 | 30 | read | old | disposed |
* | 5 | 16 | 32 | not_read | old | disposed |
* | 5 | 17 | 34 | read | old | disposed |
* | 6 | 18 | 36 | read | old | no_writers |
* | 6 | 19 | 38 | not_read | old | no_writers |
* | 6 | 20 | 40 | read | old | no_writers |
*
*/
#define MAX_SAMPLES 21
#define RDR_NOT_READ_CNT 11
int rdr_expected_long_2[RDR_NOT_READ_CNT] = { 0, 1, 2, 6, 7, 9, 11, 13, 14, 16, 19 };
/* Because we only read one sample at a time, only the first sample of an instance
* can be new. This turns out to be only the very first sample. */
#define SAMPLE_VST(long_2) ((long_2 == 0) ? DDS_VST_NEW : DDS_VST_OLD)
#define SAMPLE_IST(long_1) ((long_1 == 5) ? DDS_IST_NOT_ALIVE_DISPOSED : \
(long_1 == 6) ? DDS_IST_NOT_ALIVE_NO_WRITERS : \
DDS_IST_ALIVE )
static dds_entity_t g_participant = 0;
static dds_entity_t g_subscriber = 0;
static dds_entity_t g_publisher = 0;
static dds_entity_t g_topic = 0;
static dds_entity_t g_reader = 0;
static dds_entity_t g_writer = 0;
static dds_entity_t g_waitset = 0;
static dds_entity_t g_rcond = 0;
static dds_entity_t g_qcond = 0;
static void* g_loans[MAX_SAMPLES];
static void* g_samples[MAX_SAMPLES];
static Space_Type1 g_data[MAX_SAMPLES];
static dds_sample_info_t g_info[MAX_SAMPLES];
static dds_instance_handle_t g_hdl_valid;
static dds_instance_handle_t g_hdl_nil = DDS_HANDLE_NIL;
static char*
create_topic_name(const char *prefix, char *name, size_t size)
{
/* Get semi random g_topic name. */
os_procId pid = os_procIdSelf();
uintmax_t tid = os_threadIdToInteger(os_threadIdSelf());
(void) snprintf(name, size, "%s_pid%"PRIprocId"_tid%"PRIuMAX"", prefix, pid, tid);
return name;
}
static bool
filter_init(const void * sample)
{
const Space_Type1 *s = sample;
return ((s->long_2 == 3) ||
(s->long_2 == 4) ||
(s->long_2 == 5) ||
(s->long_2 == 8) ||
(s->long_2 == 10) ||
(s->long_2 == 12) ||
(s->long_2 == 15) ||
(s->long_2 == 17) ||
(s->long_2 == 18) ||
(s->long_2 == 20));
}
static bool
filter_mod2(const void * sample)
{
const Space_Type1 *s = sample;
return (s->long_2 % 2 == 0);
}
static void
reader_iterator_init(void)
{
Space_Type1 sample = { 0 };
dds_attach_t triggered;
dds_return_t ret;
char name[100];
dds_qos_t *qos;
qos = dds_qos_create();
cr_assert_not_null(qos, "Failed to create prerequisite qos");
g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(g_participant, 0, "Failed to create prerequisite g_participant");
g_subscriber = dds_create_subscriber(g_participant, NULL, NULL);
cr_assert_gt(g_subscriber, 0, "Failed to create prerequisite g_subscriber");
g_publisher = dds_create_publisher(g_participant, NULL, NULL);
cr_assert_gt(g_publisher, 0, "Failed to create prerequisite g_publisher");
g_waitset = dds_create_waitset(g_participant);
cr_assert_gt(g_waitset, 0, "Failed to create g_waitset");
g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_topic_name("ddsc_read_iterator_test", name, sizeof name), NULL, NULL);
cr_assert_gt(g_topic, 0, "Failed to create prerequisite g_topic");
/* Create a writer that will not automatically dispose unregistered samples. */
dds_qset_writer_data_lifecycle(qos, false);
g_writer = dds_create_writer(g_publisher, g_topic, qos, NULL);
cr_assert_gt(g_writer, 0, "Failed to create prerequisite g_writer");
/* Create a reader that keeps all samples when not taken. */
dds_qset_history(qos, DDS_HISTORY_KEEP_ALL, DDS_LENGTH_UNLIMITED);
g_reader = dds_create_reader(g_subscriber, g_topic, qos, NULL);
cr_assert_gt(g_reader, 0, "Failed to create prerequisite g_reader");
/* Create a read condition that only reads old samples. */
g_rcond = dds_create_readcondition(g_reader, DDS_NOT_READ_SAMPLE_STATE | DDS_NOT_NEW_VIEW_STATE | DDS_ANY_INSTANCE_STATE);
cr_assert_gt(g_rcond, 0, "Failed to create prerequisite g_rcond");
/* Create a query condition that only reads of instances mod2. */
g_qcond = dds_create_querycondition(g_reader, DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE, filter_mod2);
cr_assert_gt(g_qcond, 0, "Failed to create prerequisite g_qcond");
/* Sync g_reader to g_writer. */
ret = dds_set_enabled_status(g_reader, DDS_SUBSCRIPTION_MATCHED_STATUS);
cr_assert_eq(ret, DDS_RETCODE_OK, "Failed to set prerequisite g_reader status");
ret = dds_waitset_attach(g_waitset, g_reader, g_reader);
cr_assert_eq(ret, DDS_RETCODE_OK, "Failed to attach prerequisite g_reader");
ret = dds_waitset_wait(g_waitset, &triggered, 1, DDS_SECS(1));
cr_assert_eq(ret, 1, "Failed prerequisite dds_waitset_wait g_reader r");
cr_assert_eq(g_reader, (dds_entity_t)(intptr_t)triggered, "Failed prerequisite dds_waitset_wait g_reader a");
ret = dds_waitset_detach(g_waitset, g_reader);
cr_assert_eq(ret, DDS_RETCODE_OK, "Failed to detach prerequisite g_reader");
/* Sync g_writer to g_reader. */
ret = dds_set_enabled_status(g_writer, DDS_PUBLICATION_MATCHED_STATUS);
cr_assert_eq(ret, DDS_RETCODE_OK, "Failed to set prerequisite g_writer status");
ret = dds_waitset_attach(g_waitset, g_writer, g_writer);
cr_assert_eq(ret, DDS_RETCODE_OK, "Failed to attach prerequisite g_writer");
ret = dds_waitset_wait(g_waitset, &triggered, 1, DDS_SECS(1));
cr_assert_eq(ret, 1, "Failed prerequisite dds_waitset_wait g_writer r");
cr_assert_eq(g_writer, (dds_entity_t)(intptr_t)triggered, "Failed prerequisite dds_waitset_wait g_writer a");
ret = dds_waitset_detach(g_waitset, g_writer);
cr_assert_eq(ret, DDS_RETCODE_OK, "Failed to detach prerequisite g_writer");
/* Initialize reading buffers. */
memset (g_data, 0, sizeof (g_data));
for (int i = 0; i < MAX_SAMPLES; i++) {
g_samples[i] = &g_data[i];
}
for (int i = 0; i < MAX_SAMPLES; i++) {
g_loans[i] = NULL;
}
/* Write the samples. */
for (int i = 0; i < MAX_SAMPLES; i++) {
sample.long_1 = i/3;
sample.long_2 = i;
sample.long_3 = i*2;
ret = dds_write(g_writer, &sample);
cr_assert_eq(ret, DDS_RETCODE_OK, "Failed prerequisite write");
}
/* | long_1 | long_2 | long_3 | sst | vst | ist |
* -----------------------------------------------------
* | 0 | 0 | 0 | not_read | new | alive |
* | 0 | 1 | 2 | not_read | new | alive |
* | 0 | 2 | 4 | not_read | new | alive |
* | 1 | 3 | 6 | not_read | new | alive |
* | 1 | 4 | 8 | not_read | new | alive |
* | 1 | 5 | 10 | not_read | new | alive |
* | 2 | 6 | 12 | not_read | new | alive |
* | 2 | 7 | 14 | not_read | new | alive |
* | 2 | 8 | 16 | not_read | new | alive |
* | 3 | 9 | 18 | not_read | new | alive |
* | 3 | 10 | 20 | not_read | new | alive |
* | 3 | 11 | 22 | not_read | new | alive |
* | 4 | 12 | 24 | not_read | new | alive |
* | 4 | 13 | 26 | not_read | new | alive |
* | 4 | 14 | 28 | not_read | new | alive |
* | 5 | 15 | 30 | not_read | new | alive |
* | 5 | 16 | 32 | not_read | new | alive |
* | 5 | 17 | 34 | not_read | new | alive |
* | 6 | 18 | 36 | not_read | new | alive |
* | 6 | 19 | 38 | not_read | new | alive |
* | 6 | 20 | 40 | not_read | new | alive |
*/
/* Set the sst to read for the proper samples by using a query
* condition that filters for these specific samples. */
{
dds_entity_t qcond = 0;
/* Create a query condition that reads the specific sample to get a set of 'read' samples after init. */
qcond = dds_create_querycondition(g_reader, DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE, filter_init);
cr_assert_gt(g_qcond, 0, "Failed to create prerequisite qcond");
ret = dds_read(qcond, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES);
cr_assert_gt(ret, 0, "Failed prerequisite read: %d", dds_err_nr(ret));
dds_delete(qcond);
}
/* | long_1 | long_2 | long_3 | sst | vst | ist |
* -----------------------------------------------------
* | 0 | 0 | 0 | not_read | new | alive |
* | 0 | 1 | 2 | not_read | new | alive |
* | 0 | 2 | 4 | not_read | new | alive |
* | 1 | 3 | 6 | read | old | alive |
* | 1 | 4 | 8 | read | old | alive |
* | 1 | 5 | 10 | read | old | alive |
* | 2 | 6 | 12 | not_read | old | alive |
* | 2 | 7 | 14 | not_read | old | alive |
* | 2 | 8 | 16 | read | old | alive |
* | 3 | 9 | 18 | not_read | old | alive |
* | 3 | 10 | 20 | read | old | alive |
* | 3 | 11 | 22 | not_read | old | alive |
* | 4 | 12 | 24 | read | old | alive |
* | 4 | 13 | 26 | not_read | old | alive |
* | 4 | 14 | 28 | not_read | old | alive |
* | 5 | 15 | 30 | read | old | alive |
* | 5 | 16 | 32 | not_read | old | alive |
* | 5 | 17 | 34 | read | old | alive |
* | 6 | 18 | 36 | read | old | alive |
* | 6 | 19 | 38 | not_read | old | alive |
* | 6 | 20 | 40 | read | old | alive |
*/
/* Dispose and unregister the last two samples. */
sample.long_1 = 5;
sample.long_2 = 15;
sample.long_3 = 30;
ret = dds_dispose(g_writer, &sample);
cr_assert_eq(ret, DDS_RETCODE_OK, "Failed prerequisite dispose");
sample.long_1 = 6;
sample.long_2 = 16;
sample.long_3 = 32;
ret = dds_unregister_instance(g_writer, &sample);
cr_assert_eq(ret, DDS_RETCODE_OK, "Failed prerequisite unregister");
/* | long_1 | long_2 | long_3 | sst | vst | ist |
* ----------------------------------------------------------
* | 0 | 0 | 0 | not_read | new | alive |
* | 0 | 1 | 2 | not_read | new | alive |
* | 0 | 2 | 4 | not_read | new | alive |
* | 1 | 3 | 6 | read | old | alive |
* | 1 | 4 | 8 | read | old | alive |
* | 1 | 5 | 10 | read | old | alive |
* | 2 | 6 | 12 | not_read | old | alive |
* | 2 | 7 | 14 | not_read | old | alive |
* | 2 | 8 | 16 | read | old | alive |
* | 3 | 9 | 18 | not_read | old | alive |
* | 3 | 10 | 20 | read | old | alive |
* | 3 | 11 | 22 | not_read | old | alive |
* | 4 | 12 | 24 | read | old | alive |
* | 4 | 13 | 26 | not_read | old | alive |
* | 4 | 14 | 28 | not_read | old | alive |
* | 5 | 15 | 30 | read | old | disposed |
* | 5 | 16 | 32 | not_read | old | disposed |
* | 5 | 17 | 34 | read | old | disposed |
* | 6 | 18 | 36 | read | old | no_writers |
* | 6 | 19 | 38 | not_read | old | no_writers |
* | 6 | 20 | 40 | read | old | no_writers |
*/
dds_qos_delete(qos);
}
static void
reader_iterator_fini(void)
{
dds_delete(g_rcond);
dds_delete(g_qcond);
dds_delete(g_reader);
dds_delete(g_writer);
dds_delete(g_subscriber);
dds_delete(g_publisher);
dds_delete(g_waitset);
dds_delete(g_topic);
dds_delete(g_participant);
}
static dds_return_t
samples_cnt(void)
{
dds_return_t ret;
ret = dds_read(g_reader, g_samples, g_info, MAX_SAMPLES, MAX_SAMPLES);
cr_assert_geq(ret, 0, "Failed samples count read: %d", dds_err_nr(ret));
return ret;
}
/**************************************************************************************************
*
* These will check the dds_read_next() in various ways.
*
*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_read_next, reader, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_return_t cnt = 0;
dds_return_t ret = 1;
while (ret == 1){
ret = dds_read_next(g_reader, g_samples, g_info);
cr_assert_geq(ret, 0 , "# read %d", ret);
if(ret == 1){
Space_Type1 *sample = (Space_Type1*)g_samples[0];
PRINT_SAMPLE("ddsc_read_next::reader: Read", (*sample));
/* Expected states. */
int expected_long_2 = rdr_expected_long_2[cnt];
int expected_long_1 = expected_long_2/3;
int expected_long_3 = expected_long_2*2;
dds_sample_state_t expected_sst = DDS_SST_NOT_READ;
dds_view_state_t expected_vst = SAMPLE_VST(expected_long_2);
dds_instance_state_t expected_ist = SAMPLE_IST(expected_long_1);
/* Check data. */
cr_assert_eq(sample->long_1, expected_long_1 );
cr_assert_eq(sample->long_2, expected_long_2 );
cr_assert_eq(sample->long_3, expected_long_2 *2);
/* Check states. */
cr_assert_eq(g_info[0].valid_data, true);
cr_assert_eq(g_info[0].sample_state, expected_sst);
cr_assert_eq(g_info[0].view_state, expected_vst);
cr_assert_eq(g_info[0].instance_state, expected_ist);
cnt ++;
}
}
cr_assert_eq(cnt, RDR_NOT_READ_CNT);
/* All samples should still be available. */
ret = samples_cnt();
cr_assert_eq(ret, MAX_SAMPLES, "# samples %d, expected %d", ret, MAX_SAMPLES);
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_read_next, invalid_readers) = {
DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN),
};
Theory((dds_entity_t rdr), ddsc_read_next, invalid_readers, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1;
dds_return_t ret;
ret = dds_read_next(rdr, g_samples, g_info);
cr_assert_eq(dds_err_nr(ret), dds_err_nr(exp), "returned %d != expected %d", dds_err_str(ret), dds_err_nr(exp));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_read_next, non_readers) = {
DataPoints(dds_entity_t*, &g_participant, &g_topic, &g_writer, &g_subscriber, &g_publisher, &g_waitset, &g_rcond, &g_qcond),
};
Theory((dds_entity_t *rdr), ddsc_read_next, non_readers, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_return_t ret;
ret = dds_read_next(*rdr, g_samples, g_info);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION, "returned %d", dds_err_nr(ret));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_read_next, already_deleted) = {
DataPoints(dds_entity_t*, &g_rcond, &g_qcond, &g_reader),
};
Theory((dds_entity_t *rdr), ddsc_read_next, already_deleted, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_return_t ret;
ret = dds_delete(*rdr);
cr_assert_eq(ret, DDS_RETCODE_OK, "prerequisite delete failed: %d", dds_err_nr(ret));
ret = dds_read_next(*rdr, g_samples, g_info);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED, "returned %d", dds_err_nr(ret));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_read_next, invalid_buffers) = {
DataPoints(void**, g_samples, g_loans, (void**)0),
DataPoints(dds_sample_info_t*, g_info, (dds_sample_info_t*)0 ),
};
Theory((void **buf, dds_sample_info_t *si), ddsc_read_next, invalid_buffers, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_return_t ret;
cr_assume((buf != g_samples) || (si != g_info));
cr_assume(buf != g_loans);
ret = dds_read_next(g_reader, buf, si);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER, "returned %d", dds_err_nr(ret));
}
/*************************************************************************************************/
/**************************************************************************************************
*
* These will check the dds_read_next_wl() in various ways.
*
*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_read_next_wl, reader, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_return_t cnt = 0;
dds_return_t ret = 1;
while (ret == 1){
ret = dds_read_next_wl(g_reader, g_loans, g_info);
cr_assert_geq(ret, 0 , "# read %d", ret);
if(ret == 1){
Space_Type1 *sample = (Space_Type1*)g_loans[0];
PRINT_SAMPLE("ddsc_read_next_wl::reader: Read", (*sample));
/* Expected states. */
int expected_long_2 = rdr_expected_long_2[cnt];
int expected_long_1 = expected_long_2/3;
int expected_long_3 = expected_long_2*2;
dds_sample_state_t expected_sst = DDS_SST_NOT_READ;
dds_view_state_t expected_vst = SAMPLE_VST(expected_long_2);
dds_instance_state_t expected_ist = SAMPLE_IST(expected_long_1);
/* Check data. */
cr_assert_eq(sample->long_1, expected_long_2/3 );
cr_assert_eq(sample->long_2, expected_long_2 );
cr_assert_eq(sample->long_3, expected_long_2 *2);
/* Check states. */
cr_assert_eq(g_info[0].valid_data, true);
cr_assert_eq(g_info[0].sample_state, expected_sst);
cr_assert_eq(g_info[0].view_state, expected_vst);
cr_assert_eq(g_info[0].instance_state, expected_ist);
cnt ++;
}
}
cr_assert_eq(cnt, RDR_NOT_READ_CNT);
ret = dds_return_loan(g_reader, g_loans, ret);
cr_assert_eq (ret, DDS_RETCODE_OK);
/* All samples should still be available. */
ret = samples_cnt();
cr_assert_eq(ret, MAX_SAMPLES, "# samples %d, expected %d", ret, MAX_SAMPLES);
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_read_next_wl, invalid_readers) = {
DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN),
};
Theory((dds_entity_t rdr), ddsc_read_next_wl, invalid_readers, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1;
dds_return_t ret;
ret = dds_read_next_wl(rdr, g_loans, g_info);
cr_assert_eq(dds_err_nr(ret), dds_err_nr(exp), "returned %d != expected %d", dds_err_nr(ret), dds_err_nr(exp));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_read_next_wl, non_readers) = {
DataPoints(dds_entity_t*, &g_participant, &g_topic, &g_writer, &g_subscriber, &g_publisher, &g_waitset, &g_rcond, &g_qcond),
};
Theory((dds_entity_t *rdr), ddsc_read_next_wl, non_readers, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_return_t ret;
ret = dds_read_next_wl(*rdr, g_loans, g_info);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION, "returned %d", dds_err_nr(ret));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_read_next_wl, already_deleted) = {
DataPoints(dds_entity_t*, &g_rcond, &g_qcond, &g_reader),
};
Theory((dds_entity_t *rdr), ddsc_read_next_wl, already_deleted, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_return_t ret;
ret = dds_delete(*rdr);
cr_assert_eq(ret, DDS_RETCODE_OK, "prerequisite delete failed: %d", dds_err_nr(ret));
ret = dds_read_next_wl(*rdr, g_loans, g_info);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED, "returned %d", dds_err_nr(ret));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_read_next_wl, invalid_buffers) = {
DataPoints(void**, g_loans, (void**)0),
DataPoints(dds_sample_info_t*, g_info, (dds_sample_info_t*)0 ),
};
Theory((void **buf, dds_sample_info_t *si), ddsc_read_next_wl, invalid_buffers, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_return_t ret;
cr_assume((buf != g_loans) || (si != g_info));
ret = dds_read_next_wl(g_reader, buf, si);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER, "returned %d", dds_err_nr(ret));
}
/*************************************************************************************************/
/**************************************************************************************************
*
* These will check the dds_take_next() in various ways.
*
*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_take_next, reader, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_return_t cnt = 0;
dds_return_t ret = 1;
while (ret == 1){
ret = dds_take_next(g_reader, g_samples, g_info);
cr_assert_geq(ret, 0 , "# read %d", ret);
if(ret == 1){
Space_Type1 *sample = (Space_Type1*)g_samples[0];
PRINT_SAMPLE("ddsc_take_next::reader: Read", (*sample));
/* Expected states. */
int expected_long_2 = rdr_expected_long_2[cnt];
int expected_long_1 = expected_long_2/3;
int expected_long_3 = expected_long_2*2;
dds_sample_state_t expected_sst = DDS_SST_NOT_READ;
dds_view_state_t expected_vst = SAMPLE_VST(expected_long_2);
dds_instance_state_t expected_ist = SAMPLE_IST(expected_long_1);
/* Check data. */
cr_assert_eq(sample->long_1, expected_long_1 );
cr_assert_eq(sample->long_2, expected_long_2 );
cr_assert_eq(sample->long_3, expected_long_2 *2);
/* Check states. */
cr_assert_eq(g_info[0].valid_data, true);
cr_assert_eq(g_info[0].sample_state, expected_sst);
cr_assert_eq(g_info[0].view_state, expected_vst);
cr_assert_eq(g_info[0].instance_state, expected_ist);
cnt ++;
}
}
cr_assert_eq(cnt, RDR_NOT_READ_CNT);
/* All samples should still be available. */
ret = samples_cnt();
cr_assert_eq(ret, (MAX_SAMPLES - RDR_NOT_READ_CNT), "# samples %d, expected %d", ret, MAX_SAMPLES);
}
/*************************************************************************************************/
TheoryDataPoints(ddsc_take_next, invalid_readers) = {
DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN),
};
Theory((dds_entity_t rdr), ddsc_take_next, invalid_readers, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1;
dds_return_t ret;
ret = dds_take_next(rdr, g_samples, g_info);
cr_assert_eq(dds_err_nr(ret), dds_err_nr(exp), "returned %d != expected %d", dds_err_nr(ret), dds_err_nr(exp));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_take_next, non_readers) = {
DataPoints(dds_entity_t*, &g_participant, &g_topic, &g_writer, &g_subscriber, &g_publisher, &g_waitset, &g_rcond, &g_qcond),
};
Theory((dds_entity_t *rdr), ddsc_take_next, non_readers, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_return_t ret;
ret = dds_take_next(*rdr, g_samples, g_info);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION, "returned %d", dds_err_nr(ret));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_take_next, already_deleted) = {
DataPoints(dds_entity_t*, &g_rcond, &g_qcond, &g_reader),
};
Theory((dds_entity_t *rdr), ddsc_take_next, already_deleted, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_return_t ret;
ret = dds_delete(*rdr);
cr_assert_eq(ret, DDS_RETCODE_OK, "prerequisite delete failed: %d", dds_err_nr(ret));
ret = dds_take_next(*rdr, g_samples, g_info);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED, "returned %d", dds_err_nr(ret));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_take_next, invalid_buffers) = {
DataPoints(void**, g_samples, g_loans, (void**)0),
DataPoints(dds_sample_info_t*, g_info, (dds_sample_info_t*)0 ),
};
Theory((void **buf, dds_sample_info_t *si), ddsc_take_next, invalid_buffers, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_return_t ret;
cr_assume((buf != g_samples) || (si != g_info));
cr_assume(buf != g_loans);
ret = dds_take_next(g_reader, buf, si);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER, "returned %d", dds_err_nr(ret));
}
/*************************************************************************************************/
/**************************************************************************************************
*
* These will check the dds_take_next_wl() in various ways.
*
*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_take_next_wl, reader, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_return_t cnt = 0;
dds_return_t ret = 1;
while (ret == 1){
ret = dds_take_next_wl(g_reader, g_loans, g_info);
cr_assert_geq(ret, 0 , "# read %d", ret);
if(ret == 1){
Space_Type1 *sample = (Space_Type1*)g_loans[0];
PRINT_SAMPLE("ddsc_read_next_wl::reader: Read", (*sample));
/* Expected states. */
int expected_long_2 = rdr_expected_long_2[cnt];
int expected_long_1 = expected_long_2/3;
int expected_long_3 = expected_long_2*2;
dds_sample_state_t expected_sst = DDS_SST_NOT_READ;
dds_view_state_t expected_vst = SAMPLE_VST(expected_long_2);
dds_instance_state_t expected_ist = SAMPLE_IST(expected_long_1);
/* Check data. */
cr_assert_eq(sample->long_1, expected_long_2/3 );
cr_assert_eq(sample->long_2, expected_long_2 );
cr_assert_eq(sample->long_3, expected_long_2 *2);
/* Check states. */
cr_assert_eq(g_info[0].valid_data, true);
cr_assert_eq(g_info[0].sample_state, expected_sst);
cr_assert_eq(g_info[0].view_state, expected_vst);
cr_assert_eq(g_info[0].instance_state, expected_ist);
cnt ++;
}
}
cr_assert_eq(cnt, RDR_NOT_READ_CNT);
ret = dds_return_loan(g_reader, g_loans, ret);
cr_assert_eq (ret, DDS_RETCODE_OK);
/* All samples should still be available. */
ret = samples_cnt();
cr_assert_eq(ret, (MAX_SAMPLES - RDR_NOT_READ_CNT), "# samples %d, expected %d", ret, MAX_SAMPLES);
}
/*************************************************************************************************/
TheoryDataPoints(ddsc_take_next_wl, invalid_readers) = {
DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN),
};
Theory((dds_entity_t rdr), ddsc_take_next_wl, invalid_readers, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1;
dds_return_t ret;
ret = dds_take_next_wl(rdr, g_loans, g_info);
cr_assert_eq(dds_err_nr(ret), dds_err_nr(exp), "returned %d != expected %d", dds_err_nr(ret), dds_err_nr(exp));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_take_next_wl, non_readers) = {
DataPoints(dds_entity_t*, &g_participant, &g_topic, &g_writer, &g_subscriber, &g_publisher, &g_waitset, &g_rcond, &g_qcond),
};
Theory((dds_entity_t *rdr), ddsc_take_next_wl, non_readers, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_return_t ret;
ret = dds_take_next_wl(*rdr, g_loans, g_info);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION, "returned %d", dds_err_nr(ret));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_take_next_wl, already_deleted) = {
DataPoints(dds_entity_t*, &g_rcond, &g_qcond, &g_reader),
};
Theory((dds_entity_t *rdr), ddsc_take_next_wl, already_deleted, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_return_t ret;
ret = dds_delete(*rdr);
cr_assert_eq(ret, DDS_RETCODE_OK, "prerequisite delete failed: %d", dds_err_nr(ret));
ret = dds_take_next_wl(*rdr, g_loans, g_info);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED, "returned %d", dds_err_nr(ret));
}
/*************************************************************************************************/
/*************************************************************************************************/
TheoryDataPoints(ddsc_take_next_wl, invalid_buffers) = {
DataPoints(void**, g_loans, (void**)0),
DataPoints(dds_sample_info_t*, g_info, (dds_sample_info_t*)0 ),
};
Theory((void **buf, dds_sample_info_t *si), ddsc_take_next_wl, invalid_buffers, .init=reader_iterator_init, .fini=reader_iterator_fini)
{
dds_return_t ret;
cr_assume((buf != g_loans) || (si != g_info));
ret = dds_take_next_wl(g_reader, buf, si);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER, "returned %d", dds_err_nr(ret));
}
/*************************************************************************************************/

View file

@ -0,0 +1,227 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include <assert.h>
#include "ddsc/dds.h"
#include "os/os.h"
#include <criterion/criterion.h>
#include <criterion/logging.h>
#include <criterion/theories.h>
#include "Space.h"
/**************************************************************************************************
*
* Test fixtures
*
*************************************************************************************************/
#define MAX_SAMPLES 7
#define INITIAL_SAMPLES 2
static dds_entity_t g_participant = 0;
static dds_entity_t g_topic = 0;
static dds_entity_t g_reader = 0;
static dds_entity_t g_writer = 0;
static dds_entity_t g_waitset = 0;
static dds_time_t g_past = 0;
static dds_time_t g_present = 0;
static void* g_samples[MAX_SAMPLES];
static Space_Type1 g_data[MAX_SAMPLES];
static dds_sample_info_t g_info[MAX_SAMPLES];
static char*
create_topic_name(const char *prefix, char *name, size_t size)
{
/* Get semi random g_topic name. */
os_procId pid = os_procIdSelf();
uintmax_t tid = os_threadIdToInteger(os_threadIdSelf());
(void) snprintf(name, size, "%s_pid%"PRIprocId"_tid%"PRIuMAX"", prefix, pid, tid);
return name;
}
static void
registering_init(void)
{
Space_Type1 sample = { 0 };
dds_qos_t *qos = dds_qos_create ();
dds_attach_t triggered;
dds_return_t ret;
char name[100];
/* Use by source timestamp to be able to check the time related funtions. */
dds_qset_destination_order(qos, DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP);
g_participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(g_participant, 0, "Failed to create prerequisite g_participant");
g_waitset = dds_create_waitset(g_participant);
cr_assert_gt(g_waitset, 0, "Failed to create g_waitset");
g_topic = dds_create_topic(g_participant, &Space_Type1_desc, create_topic_name("ddsc_registering_test", name, sizeof name), qos, NULL);
cr_assert_gt(g_topic, 0, "Failed to create prerequisite g_topic");
/* Create a reader that keeps one sample on three instances. */
dds_qset_reliability(qos, DDS_RELIABILITY_RELIABLE, DDS_MSECS(100));
dds_qset_resource_limits(qos, DDS_LENGTH_UNLIMITED, 3, 1);
g_reader = dds_create_reader(g_participant, g_topic, qos, NULL);
cr_assert_gt(g_reader, 0, "Failed to create prerequisite g_reader");
/* Create a writer that will not automatically dispose unregistered samples. */
dds_qset_writer_data_lifecycle(qos, false);
g_writer = dds_create_writer(g_participant, g_topic, qos, NULL);
cr_assert_gt(g_writer, 0, "Failed to create prerequisite g_writer");
/* Sync g_writer to g_reader. */
ret = dds_set_enabled_status(g_writer, DDS_PUBLICATION_MATCHED_STATUS);
cr_assert_eq(ret, DDS_RETCODE_OK, "Failed to set prerequisite g_writer status");
ret = dds_waitset_attach(g_waitset, g_writer, g_writer);
cr_assert_eq(ret, DDS_RETCODE_OK, "Failed to attach prerequisite g_writer");
ret = dds_waitset_wait(g_waitset, &triggered, 1, DDS_SECS(1));
cr_assert_eq(ret, 1, "Failed prerequisite dds_waitset_wait g_writer r");
cr_assert_eq(g_writer, (dds_entity_t)(intptr_t)triggered, "Failed prerequisite dds_waitset_wait g_writer a");
ret = dds_waitset_detach(g_waitset, g_writer);
cr_assert_eq(ret, DDS_RETCODE_OK, "Failed to detach prerequisite g_writer");
/* Sync g_reader to g_writer. */
ret = dds_set_enabled_status(g_reader, DDS_SUBSCRIPTION_MATCHED_STATUS);
cr_assert_eq(ret, DDS_RETCODE_OK, "Failed to set prerequisite g_reader status");
ret = dds_waitset_attach(g_waitset, g_reader, g_reader);
cr_assert_eq(ret, DDS_RETCODE_OK, "Failed to attach prerequisite g_reader");
ret = dds_waitset_wait(g_waitset, &triggered, 1, DDS_SECS(1));
cr_assert_eq(ret, 1, "Failed prerequisite dds_waitset_wait g_reader r");
cr_assert_eq(g_reader, (dds_entity_t)(intptr_t)triggered, "Failed prerequisite dds_waitset_wait g_reader a");
ret = dds_waitset_detach(g_waitset, g_reader);
cr_assert_eq(ret, DDS_RETCODE_OK, "Failed to detach prerequisite g_reader");
/* Write initial samples. */
for (int i = 0; i < INITIAL_SAMPLES; i++) {
sample.long_1 = i;
sample.long_2 = i*2;
sample.long_3 = i*3;
ret = dds_write(g_writer, &sample);
cr_assert_eq(ret, DDS_RETCODE_OK, "Failed prerequisite write");
}
/* Initialize reading buffers. */
memset (g_data, 0, sizeof (g_data));
for (int i = 0; i < MAX_SAMPLES; i++) {
g_samples[i] = &g_data[i];
}
/* Initialize times. */
g_present = dds_time();
g_past = g_present - DDS_SECS(1);
dds_qos_delete(qos);
}
static void
registering_fini(void)
{
dds_delete(g_reader);
dds_delete(g_writer);
dds_delete(g_waitset);
dds_delete(g_topic);
dds_delete(g_participant);
}
#if 0
#else
/**************************************************************************************************
*
* These will check the dds_register_instance() in various ways.
*
*************************************************************************************************/
/*************************************************************************************************/
Test(ddsc_register_instance, deleted_entity, .init=registering_init, .fini=registering_fini)
{
dds_return_t ret;
dds_instance_handle_t handle;
dds_delete(g_writer);
ret = dds_register_instance(g_writer, &handle, g_data);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ALREADY_DELETED, "returned %d", dds_err_nr(ret));
}
static dds_instance_handle_t hndle = 0;
static Space_Type1 data;
TheoryDataPoints(ddsc_register_instance, invalid_params) = {
DataPoints(dds_instance_handle_t *, &hndle, NULL),
DataPoints(void*, &data, NULL)
};
Theory((dds_instance_handle_t *hndl2, void *datap), ddsc_register_instance, invalid_params/*, .init=registering_init, .fini=registering_fini*/)
{
dds_return_t exp = DDS_RETCODE_BAD_PARAMETER * -1;
dds_return_t ret;
/* Only test when the combination of parameters is actually invalid.*/
cr_assume((hndl2 == NULL) || (datap == NULL));
OS_WARNING_MSVC_OFF(6387); /* Disable SAL warning on intentional misuse of the API */
ret = dds_register_instance(g_writer, hndl2, datap);
OS_WARNING_MSVC_ON(6387);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER, "returned %d != expected %d", dds_err_nr(ret), DDS_RETCODE_BAD_PARAMETER);
}
TheoryDataPoints(ddsc_register_instance, invalid_writers) = {
DataPoints(dds_entity_t, -2, -1, 0, 1, 100, INT_MAX, INT_MIN),
};
Theory((dds_entity_t writer), ddsc_register_instance, invalid_writers, .init=registering_init, .fini=registering_fini)
{
dds_entity_t exp = DDS_RETCODE_BAD_PARAMETER * -1;
dds_return_t ret;
dds_instance_handle_t handle;
ret = dds_register_instance(writer, &handle, g_data);
cr_assert_eq(dds_err_nr(ret), dds_err_nr(exp), "returned %d != expected %d", dds_err_nr(ret), dds_err_nr(exp));
}
TheoryDataPoints(ddsc_register_instance, non_writers) = {
DataPoints(dds_entity_t*, &g_waitset, &g_reader, &g_topic, &g_participant),
};
Theory((dds_entity_t *writer), ddsc_register_instance, non_writers, .init=registering_init, .fini=registering_fini)
{
dds_return_t ret;
dds_instance_handle_t handle;
ret = dds_register_instance(*writer, &handle, g_data);
cr_assert_eq(dds_err_nr(ret), DDS_RETCODE_ILLEGAL_OPERATION, "returned %d", dds_err_nr(ret));
}
Test(ddsc_register_instance, registering_new_instance, .init=registering_init, .fini=registering_fini)
{
dds_instance_handle_t instHndl, instHndl2;
dds_return_t ret;
Space_Type1 newInstance = { INITIAL_SAMPLES, 0, 0 };
instHndl = dds_instance_lookup(g_writer, &newInstance);
cr_assert_eq(instHndl, DDS_HANDLE_NIL);
ret = dds_register_instance(g_writer, &instHndl2, &newInstance);
cr_assert_eq(ret, DDS_RETCODE_OK);
instHndl = dds_instance_lookup(g_writer, &newInstance);
cr_assert_eq(instHndl, instHndl2);
}
Test(ddsc_register_instance, data_already_available, .init=registering_init, .fini=registering_fini)
{
dds_instance_handle_t instHndl, instHndl2;
dds_return_t ret;
instHndl = dds_instance_lookup(g_writer, &g_data);
cr_assert_neq(instHndl, DDS_HANDLE_NIL);
ret = dds_register_instance(g_writer, &instHndl2, &g_data);
cr_assert_eq(ret, DDS_RETCODE_OK);
cr_assert_eq(instHndl2, instHndl);
}
#endif

View file

@ -0,0 +1,150 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "ddsc/dds.h"
#include "RoundTrip.h"
#include "os/os.h"
#include <stdio.h>
#include <criterion/criterion.h>
#include <criterion/logging.h>
dds_entity_t participant = 0, topic = 0, reader = 0, read_condition = 0;
void create_entities(void)
{
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0);
topic = dds_create_topic(participant, &RoundTripModule_DataType_desc, "ddsc_reader_return_loan_RoundTrip", NULL, NULL);
cr_assert_gt(topic, 0);
reader = dds_create_reader(participant, topic, NULL, NULL);
cr_assert_gt(reader, 0);
read_condition = dds_create_readcondition(reader, DDS_ANY_STATE);
cr_assert_gt(read_condition, 0);
}
void delete_entities(void)
{
dds_return_t result;
result = dds_delete(participant);
cr_assert_eq(dds_err_nr(result), DDS_RETCODE_OK, "Recursively delete entities, Expected(%s) Returned(%s)", DDS_TO_STRING(DDS_RETCODE_OK), dds_err_str(result));
dds_delete(read_condition);
}
static void** create_loan_buf(size_t sz, bool empty)
{
size_t i;
void **buf = NULL;
buf = dds_alloc(sz * sizeof(*buf));
for (i = 0; i < sz; i++) {
buf[i] = dds_alloc(sizeof(RoundTripModule_DataType));
if (empty) {
memset(buf[i], 0, sizeof(RoundTripModule_DataType));
} else {
RoundTripModule_DataType *s = buf[i];
s->payload._maximum = 0;
s->payload._length = 25;
s->payload._buffer = dds_alloc(25);
memset(s->payload._buffer, 'z', 25);
s->payload._release = true;
}
}
return buf;
}
static void delete_loan_buf(void **buf, size_t sz, bool empty)
{
size_t i;
for (i = 0; i < sz; i++) {
RoundTripModule_DataType *s = buf[i];
if (!empty) {
cr_expect_gt(s->payload._length, 0, "Expected allocated 'payload'-sequence in sample-contents of loan");
if (s->payload._length > 0) {
/* Freed by a successful dds_return_loan */
dds_free(s->payload._buffer);
}
}
/* dds_return_loan only free's sample contents */
dds_free(s);
}
dds_free(buf);
}
/* Verify DDS_RETCODE_BAD_PARAMETER is returned */
Test(ddsc_reader, return_loan_bad_params, .init = create_entities, .fini = delete_entities)
{
dds_return_t result;
void **buf = NULL;
result = dds_return_loan(reader, NULL, 0);
cr_expect_eq(dds_err_nr(result), DDS_RETCODE_BAD_PARAMETER, "Invalid buffer(null), Expected(%s) Returned(%s)",
DDS_TO_STRING(DDS_RETCODE_BAD_PARAMETER),
dds_err_str(result));
#pragma warning(push)
#pragma warning(disable: 6387)
result = dds_return_loan(reader, buf, 10);
#pragma warning(pop)
cr_expect_eq(dds_err_nr(result), DDS_RETCODE_BAD_PARAMETER, "Invalid buffer size, Expected(%s) Returned(%s)",
DDS_TO_STRING(DDS_RETCODE_BAD_PARAMETER),
dds_err_str(result));
buf = create_loan_buf(10, false);
#pragma warning(push)
#pragma warning(disable: 28020)
result = dds_return_loan(0, buf, 10);
#pragma warning(pop)
cr_expect_eq(dds_err_nr(result), DDS_RETCODE_BAD_PARAMETER, "Invalid entity, Expected(%s) Returned(%s)",
DDS_TO_STRING(DDS_RETCODE_BAD_PARAMETER),
dds_err_str(result));
result = dds_return_loan(participant, buf, 0);
cr_expect_eq(dds_err_nr(result), DDS_RETCODE_ILLEGAL_OPERATION, "Invalid entity-kind, Expected(%s) Returned(%s)",
DDS_TO_STRING(DDS_RETCODE_ILLEGAL_OPERATION),
dds_err_str(result));
delete_loan_buf(buf, 10, false);
}
/* Verify DDS_RETCODE_OK is returned */
Test(ddsc_reader, return_loan_success, .init = create_entities, .fini = delete_entities)
{
void **buf;
void *buf2 = NULL;
dds_return_t result;
buf = create_loan_buf(10, false);
result = dds_return_loan(reader, buf, 10);
cr_expect_eq(dds_err_nr(result), DDS_RETCODE_OK, "Return loan of size 10 via reader entity, Expected(%s) Returned(%s)",
DDS_TO_STRING(DDS_RETCODE_OK),
dds_err_str(result));
result = dds_return_loan(reader, &buf2, 0);
cr_expect_eq(dds_err_nr(result), DDS_RETCODE_OK, "Return empty loan via reader entity, Expected(%s) Returned(%s)",
DDS_TO_STRING(DDS_RETCODE_OK),
dds_err_str(result));
delete_loan_buf(buf, 10, true);
buf = create_loan_buf(10, false);
result = dds_return_loan(read_condition, buf, 10);
cr_expect_eq(dds_err_nr(result), DDS_RETCODE_OK, "Return loan of size 10 via read-condition entity, Expected(%s) Returned(%s)",
DDS_TO_STRING(DDS_RETCODE_OK),
dds_err_str(result));
result = dds_return_loan(read_condition, &buf2, 0);
cr_expect_eq(dds_err_nr(result), DDS_RETCODE_OK, "Return empty loan via read-condition entity, Expected(%s) Returned(%s)",
DDS_TO_STRING(DDS_RETCODE_OK),
dds_err_str(result));
delete_loan_buf(buf, 10, true);
}

View file

@ -0,0 +1,111 @@
/*
* Copyright(c) 2006 to 2018 ADLINK Technology Limited and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License
* v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
#include "ddsc/dds.h"
#include <stdio.h>
#include <criterion/criterion.h>
#include <criterion/logging.h>
/* We are deliberately testing some bad arguments that SAL will complain about.
* So, silence SAL regarding these issues. */
#pragma warning(push)
#pragma warning(disable: 6387 28020)
static void on_data_available(dds_entity_t reader, void* arg) {}
static void on_publication_matched(dds_entity_t writer, const dds_publication_matched_status_t status, void* arg) {}
Test(ddsc_subscriber, notify_readers) {
dds_entity_t participant;
dds_entity_t subscriber;
dds_return_t ret;
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0, "Failed to create prerequisite participant");
subscriber = dds_create_subscriber(participant, NULL, NULL);
cr_assert_gt(subscriber, 0, "Failed to create prerequisite subscriber");
/* todo implement tests */
ret = dds_notify_readers(subscriber);
cr_expect_eq(dds_err_nr(ret), DDS_RETCODE_UNSUPPORTED, "Invalid return code %d", ret);
dds_delete(subscriber);
dds_delete(participant);
}
Test(ddsc_subscriber, create) {
dds_entity_t participant;
dds_entity_t subscriber;
dds_listener_t *listener;
dds_qos_t *sqos;
participant = dds_create_participant(DDS_DOMAIN_DEFAULT, NULL, NULL);
cr_assert_gt(participant, 0, "Failed to create prerequisite participant");
/*** Verify participant parameter ***/
subscriber = dds_create_subscriber(0, NULL, NULL);
cr_assert_eq(dds_err_nr(subscriber), DDS_RETCODE_BAD_PARAMETER, "dds_create_subscriber: invalid participant parameter");
subscriber = dds_create_subscriber(participant, NULL, NULL);
cr_assert_gt(subscriber, 0, "dds_create_subscriber: valid participant parameter");
dds_delete(subscriber);
/*** Verify qos parameter ***/
sqos = dds_qos_create(); /* Use defaults (no user-defined policies) */
subscriber = dds_create_subscriber(participant, sqos, NULL);
cr_assert_gt(subscriber, 0, "dds_create_subscriber: default QoS parameter");
dds_delete(subscriber);
dds_qos_delete(sqos);
sqos = dds_qos_create();
dds_qset_destination_order(sqos, 3); /* Set invalid dest. order (ignored, not applicable for subscriber) */
subscriber = dds_create_subscriber(participant, sqos, NULL);
cr_assert_gt(subscriber, 0, "dds_create_subscriber: invalid non-applicable QoS parameter");
dds_delete(subscriber);
dds_qos_delete(sqos);
sqos = dds_qos_create();
dds_qset_presentation(sqos, 123, 1, 1); /* Set invalid presentation policy */
subscriber = dds_create_subscriber(participant, sqos, NULL);
cr_assert_eq(dds_err_nr(subscriber), DDS_RETCODE_INCONSISTENT_POLICY, "dds_create_subscriber: invalid presentation access_scope QoS parameter");
dds_qos_delete(sqos);
/*** Verify listener parameter ***/
listener = dds_listener_create(NULL); /* Use defaults (all listeners unset) */
subscriber = dds_create_subscriber(participant, NULL, listener);
cr_assert_gt(subscriber, 0, "dds_create_subscriber: unset listeners");
dds_delete(subscriber);
dds_listener_delete(listener);
listener = dds_listener_create(NULL);
dds_lset_data_available(listener, &on_data_available); /* Set on_data_available listener */
subscriber = dds_create_subscriber(participant, NULL, listener);
cr_assert_gt(subscriber, 0, "dds_create_subscriber: on_data_available listener");
dds_delete(subscriber);
dds_listener_delete(listener);
listener = dds_listener_create(NULL);
dds_lset_publication_matched(listener, &on_publication_matched); /* Set on_publication_matched listener (ignored, not applicable for subscriber) */
subscriber = dds_create_subscriber(participant, NULL, listener);
cr_assert_gt(subscriber, 0, "dds_create_subscriber: on_publication_matched listener");
dds_delete(subscriber);
dds_listener_delete(listener);
dds_delete(participant);
}
#pragma warning(pop)

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more