SET(INCLUDEDIR "\${prefix}/${DEST_INCLUDE_DIR}")
SET(VERSION_MAJOR 0)
-SET(VERSION "${VERSION_MAJOR}.0.30")
+SET(VERSION "${VERSION_MAJOR}.1.6")
INCLUDE_DIRECTORIES(${SRC_INCLUDE_DIR})
-#SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -I${CMAKE_SOURCE_DIR}/src -I${SRC_INCLUDE_DIR} -D_NON_SLP")
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -I${CMAKE_SOURCE_DIR}/src -I${SRC_INCLUDE_DIR}")
FILE(GLOB SRCS src/*.c)
INCLUDE(FindPkgConfig)
-#pkg_check_modules(pkgs REQUIRED glib-2.0 gthread-2.0 libzmq)
-pkg_check_modules(pkgs REQUIRED glib-2.0 gthread-2.0 dlog libsystemd-daemon libzmq)
+pkg_check_modules(pkgs REQUIRED glib-2.0 gthread-2.0 dlog libsystemd-daemon)
FOREACH(flag ${pkgs_CFLAGS})
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -Wall -g -fPIC -std=c++0x")
ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"")
FILE(GLOB HEADER_FILES ${SRC_INCLUDE_DIR}/*.h)
INSTALL(FILES ${HEADER_FILES} DESTINATION ${DEST_INCLUDE_DIR})
-ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/test)
pims_ipc_data_h pims_ipc_data_create_with_size(unsigned int size, int flags);
void pims_ipc_data_destroy(pims_ipc_data_h ipc);
-int pims_ipc_data_put(pims_ipc_data_h data, void *buf, unsigned int size);
void* pims_ipc_data_get(pims_ipc_data_h data, unsigned int *size);
-void* pims_ipc_data_get_dup(pims_ipc_data_h data, unsigned int *size);
-int pims_ipc_data_put_with_type(pims_ipc_data_h data, pims_ipc_data_type_e type, void *buf, unsigned int size);
-void* pims_ipc_data_get_with_type(pims_ipc_data_h data, pims_ipc_data_type_e *type, unsigned int *size);
-void* pims_ipc_data_get_dup_with_type(pims_ipc_data_h data, pims_ipc_data_type_e *type, unsigned int *size);
-
-void* pims_ipc_data_marshal(pims_ipc_data_h data, unsigned int *size);
-int pims_ipc_data_marshal_with_zmq(pims_ipc_data_h data, zmq_msg_t *pzmsg);
-void* pims_ipc_data_marshal_dup(pims_ipc_data_h data, unsigned int *size);
-pims_ipc_data_h pims_ipc_data_unmarshal(void *buf, unsigned int size);
-pims_ipc_data_h pims_ipc_data_unmarshal_with_zmq(zmq_msg_t *pzmsg);
-pims_ipc_data_h pims_ipc_data_unmarshal_dup(void *buf, unsigned int size);
+int pims_ipc_data_put(pims_ipc_data_h data, void *buf, unsigned int size);
+
#ifdef __cplusplus
}
void pims_ipc_svc_run_main_loop(GMainLoop* main_loop);
+void pims_ipc_svc_set_client_disconnected_cb(pims_ipc_svc_client_disconnected_cb callback, void *userdata);
+
#ifdef __cplusplus
}
#endif
#ifndef __PIMS_IPC_TYPES_H__
#define __PIMS_IPC_TYPES_H__
-#include <zmq.h>
#include <glib.h>
#include <stdbool.h>
PIMS_IPC_DATA_TYPE_MEMORY,
} pims_ipc_data_type_e;
-typedef void (*pims_ipc_svc_call_cb)(pims_ipc_h ipc, pims_ipc_data_h data_in,
+typedef void (*pims_ipc_svc_call_cb)(pims_ipc_h ipc, pims_ipc_data_h data_in,
pims_ipc_data_h *data_out, void *userdata);
+typedef void (*pims_ipc_svc_client_disconnected_cb)(pims_ipc_h ipc, void *userdata);
+
typedef void (*pims_ipc_call_async_cb)(pims_ipc_h ipc, pims_ipc_data_h data_out, void *userdata);
typedef void (*pims_ipc_subscribe_cb)(pims_ipc_h ipc, pims_ipc_data_h data, void *userdata);
+
#ifdef __cplusplus
}
#endif
Name: pims-ipc
Summary: library for PIMs IPC
-Version: 0.0.30
+Version: 0.1.6
Release: 1
Group: System/Libraries
License: Apache-2.0
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(dlog)
BuildRequires: pkgconfig(libsystemd-daemon)
-BuildRequires: pkgconfig(libzmq)
%description
library for PIMs IPC
%build
+export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE"
+export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE"
+export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE"
%cmake .
make %{?jobs:-j%jobs}
%install
%make_install
-
mkdir -p %{buildroot}/usr/share/license
cp LICENSE.APLv2 %{buildroot}/usr/share/license/%{name}
%defattr(-,root,root,-)
%{_includedir}/pims-ipc/*.h
%{_libdir}/*.so
-%{_libdir}/pims_ipc_test
%{_libdir}/pkgconfig/pims-ipc.pc
Name: @PROJECT_NAME@
Description: @PROJECT_NAME@ library
Version: @VERSION@
-Requires: glib-2.0 libzmq
+Requires: glib-2.0
Libs: -L${libdir} -l@PROJECT_NAME@
Cflags: -I${includedir}
#ifndef __PIMS_DEBUG_H__
#define __PIMS_DEBUG_H__
-#ifndef _NON_SLP
-#include <dlog.h>
-#endif
#include <assert.h>
+#define LOG_TAG "PIMS_IPC"
+#include <dlog.h>
+
#ifdef __cplusplus
extern "C"
{
#endif
-/* Tag defines */
-#define TAG_IPC "PIMS_IPC"
-
-/* debug base macro */
-#ifndef _NON_SLP
-#define __ug_log(logtype, tag, frmt, args...) \
- do {LOG(logtype, tag, "%s:%s(%d) > "frmt"\n", __MODULE__, __FUNCTION__, __LINE__, ##args);} while (0)
-#else
-#define LOG_VERBOSE "VERBOSE"
-#define LOG_DEBUG "DEBUG"
-#define LOG_INFO "INFO"
-#define LOG_WARN "WARN"
-#define LOG_ERROR "ERROR"
-#define __ug_log(logtype, tag, frmt, args...) \
- do {printf("[%s][%s][%08x] %s:%s(%d) > "frmt"\n", logtype, tag, (unsigned int)pthread_self(), __FILE__, __FUNCTION__, __LINE__, ##args);} while (0)
-#endif
-
-#define pims_verbose(tag, frmt, args...) __ug_log(LOG_VERBOSE, tag, frmt, ##args)
-#define pims_debug(tag, frmt, args...) __ug_log(LOG_DEBUG, tag, frmt, ##args)
-#define pims_info(tag, frmt, args...) __ug_log(LOG_INFO, tag, frmt, ##args)
-#define pims_warn(tag, frmt, args...) __ug_log(LOG_WARN, tag, frmt, ##args)
-#define pims_error(tag, frmt, args...) __ug_log(LOG_ERROR, tag, frmt, ##args)
+#define PIMS_VERBOSE_TAG(frmt, args...) SLOGV(frmt, ##args);
+#define PIMS_DEBUG_TAG(frmt, args...) SLOGD(frmt, ##args);
+#define PIMS_INFO_TAG(frmt, args...) SLOGI(frmt, ##args);
+#define PIMS_WARN_TAG(frmt, args...) SLOGV(frmt, ##args);
+#define PIMS_ERROR_TAG(frmt, args...) SLOGE(frmt, ##args);
-#ifndef TAG_NAME // SET default TAG
-#define TAG_NAME TAG_IPC
-#endif
-#define PIMS_VERBOSE_TAG(frmt, args...) pims_verbose(TAG_NAME, frmt, ##args);
-#define PIMS_DEBUG_TAG(frmt, args...) pims_debug (TAG_NAME, frmt, ##args);
-#define PIMS_INFO_TAG(frmt, args...) pims_info (TAG_NAME, frmt, ##args);
-#define PIMS_WARN_TAG(frmt, args...) pims_warn (TAG_NAME, frmt, ##args);
-#define PIMS_ERROR_TAG(frmt, args...) pims_error (TAG_NAME, frmt, ##args);
+#define ENTER() PIMS_DEBUG_TAG(">>>>>>>> called")
+#define LEAVE() PIMS_DEBUG_TAG("<<<<<<<< ended")
//#define VERBOSE(frmt, args...) PIMS_VERBOSE_TAG(frmt, ##args)
#define VERBOSE(frmt, args...)
#define WARNING(frmt, args...) PIMS_WARN_TAG(frmt, ##args)
#define ERROR(frmt, args...) PIMS_ERROR_TAG(frmt, ##args)
+#define WARN_IF(expr, fmt, arg...) do { \
+ if (expr) { \
+ ERROR(fmt, ##arg); \
+ } \
+} while (0)
+
+
#define ASSERT(expr) \
- if (!(expr)) \
- { \
- ERROR("Assertion %s", #expr); \
- } \
- assert(expr)
+ if (!(expr)) \
+ { \
+ ERROR("Assertion %s", #expr); \
+ } \
+ assert(expr)
#ifdef __cplusplus
}
#ifndef __PIMS_INTERNAL_H__
#define __PIMS_INTERNAL_H__
-#include <zmq.h>
-
#ifdef __cplusplus
extern "C"
{
#define API __attribute__ ((visibility("default")))
#endif
-#define PIMS_IPC_MONITOR_PATH "monitor"
-#define PIMS_IPC_DEALER_PATH "dealer"
-#define PIMS_IPC_MANAGER_PATH "manager"
-#define PIMS_IPC_MONITOR2_PATH "monitor2"
+#define MAX_EPOLL_EVENT 256
+
#define PIMS_IPC_MODULE_INTERNAL "pims_ipc_internal"
#define PIMS_IPC_FUNCTION_CREATE "create"
#define PIMS_IPC_FUNCTION_DESTROY "destroy"
#define PIMS_IPC_CALL_ID_DESTROY PIMS_IPC_MODULE_INTERNAL ":" PIMS_IPC_FUNCTION_DESTROY
#define PIMS_IPC_MAKE_CALL_ID(module, function) g_strdup_printf("%s:%s", module, function)
-static inline int _pims_zmq_msg_recv(zmq_msg_t *msg, void *socket, int flags)
-{
- int ret = -1;
-
- while (1)
- {
- ret = zmq_msg_recv(msg, socket, flags);
- if (ret == -1 && errno == EINTR)
- continue;
- break;
- }
- return ret;
-}
-
-static inline int _pims_zmq_msg_send(zmq_msg_t *msg, void *socket, int flags)
-{
- int ret = -1;
-
- while (1)
- {
- ret = zmq_msg_send(msg, socket, flags);
- if (ret == -1 && errno == EINTR)
- continue;
- break;
- }
- return ret;
-}
+typedef struct {
+ unsigned int alloc_size;
+ unsigned int buf_size;
+ unsigned int free_size;
+ char *pos;
+ char *buf;
+ int flags;
+ unsigned int created:1;
+ unsigned int buf_alloced:1;
+} pims_ipc_data_s;
#ifdef __cplusplus
}
--- /dev/null
+/*
+ * PIMS IPC
+ *
+ * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef __PIMS_IPC_DATA_INTERNAL_H__
+#define __PIMS_IPC_DATA_INTERNAL_H__
+
+#include <pims-ipc-types.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+pims_ipc_data_h pims_ipc_data_steal_unmarshal(void *buf, unsigned int size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PIMS_IPC_DATA_INTERNAL_H__ */
#include <string.h>
#include <glib.h>
-#include <pims-internal.h>
-#include <pims-debug.h>
-#include <pims-ipc-data.h>
-
-typedef struct
-{
- unsigned int alloc_size;
- unsigned int buf_size;
- unsigned int free_size;
- zmq_msg_t zmsg;
- char *pos;
- char *buf;
- int flags;
- unsigned int created:1;
- unsigned int zmsg_alloced:1;
- unsigned int buf_alloced:1;
-} pims_ipc_data_t;
+#include "pims-internal.h"
+#include "pims-debug.h"
+#include "pims-ipc-data.h"
/*
- Structure of data with type(4 bytes order)
- +------------------------------------------------------------------+
- | type | size | data | pad | type | size | data | pad |
- +------------------------------------------------------------------+
- 4 4 size 0-3 (Size of bytes)
-
- Structure of data without type(4 bytes order)
- +----------------------------------------------------+
- | size | data | pad | size | data | pad |
- +----------------------------------------------------+
- 4 size 0-3 (Size of bytes)
-*/
+ Structure of data with type(4 bytes order)
+ +------------------------------------------------------------------+
+ | type | size | data | pad | type | size | data | pad |
+ +------------------------------------------------------------------+
+ 4 4 size 0-3 (Size of bytes)
+
+ Structure of data without type(4 bytes order)
+ +----------------------------------------------------+
+ | size | data | pad | size | data | pad |
+ +----------------------------------------------------+
+ 4 size 0-3 (Size of bytes)
+ */
#define _get_used_size_with_type(data_size) \
- (sizeof(int) + sizeof(int) + data_size + (sizeof(int) - (data_size % sizeof(int))))
+ (sizeof(int) + sizeof(int) + data_size + ((sizeof(int) - (data_size % sizeof(int)))%sizeof(int)))
#define _get_used_size(data_size) \
- (sizeof(int) + data_size + (sizeof(int) - (data_size % sizeof(int))))
+ (sizeof(int) + data_size + ((sizeof(int) - (data_size % sizeof(int)))%sizeof(int)))
API pims_ipc_data_h pims_ipc_data_create_with_size(unsigned int size, int flags)
{
- int ret = -1;
- pims_ipc_data_t *handle = NULL;
-
- handle = g_new0(pims_ipc_data_t, 1);
- handle->alloc_size = size;
- handle->free_size = size;
- handle->buf_size = 0;
- handle->buf = g_malloc0(size);
- handle->pos = handle->buf;
- handle->created = 1;
- handle->buf_alloced = 1;
-
- ret = pims_ipc_data_put(handle, &flags, sizeof(int));
- ASSERT(ret == 0);
- handle->flags = flags;
-
- return handle;
-}
-
-API void pims_ipc_data_destroy(pims_ipc_data_h data)
-{
- pims_ipc_data_t *handle = (pims_ipc_data_t *)data;
- if (handle->buf_alloced)
- {
- g_free(handle->buf);
- }
- if (handle->zmsg_alloced)
- {
- zmq_msg_close(&handle->zmsg);
- }
- g_free(handle);
-}
-
-API int pims_ipc_data_put(pims_ipc_data_h data, void *buf, unsigned int size)
-{
- pims_ipc_data_t *handle = NULL;
- unsigned int dsize = size;
- unsigned int used_size = 0;
- handle = (pims_ipc_data_t *)data;
-
- if (handle->created == 0)
- {
- ERROR("This handle isn't create mode.");
- return -1;
- }
- if (handle->flags & PIMS_IPC_DATA_FLAGS_WITH_TYPE)
- {
- ERROR("Not without-type mode");
- return -1;
- }
- if (dsize > 0 && buf == NULL)
- {
- ERROR("Invalid argument");
- return -1;
- }
-
- if (handle->free_size < _get_used_size(dsize))
- {
- int new_size = 0;
- new_size = handle->alloc_size * 2;
-
- while (new_size < handle->buf_size + _get_used_size(dsize))
- new_size *= 2;
- handle->buf = g_realloc(handle->buf, new_size);
- handle->alloc_size = new_size;
- handle->free_size = handle->alloc_size - handle->buf_size;
-
- handle->pos = handle->buf;
- handle->pos += handle->buf_size;
-
- VERBOSE("free_size [%d] dsize [%d]", handle->free_size, dsize);
- }
-
- *(int*)(handle->pos) = dsize;
- if (dsize > 0)
- memcpy((handle->pos+sizeof(int)), buf, dsize);
-
- used_size = _get_used_size(dsize);
- handle->pos += used_size;
- handle->buf_size += used_size;
- handle->free_size -= used_size;
-
- VERBOSE("data put size [%u] data[%p]", dsize, buf);
-
- return 0;
-}
-
-API void* pims_ipc_data_get(pims_ipc_data_h data, unsigned int *size)
-{
- pims_ipc_data_t *handle = NULL;
- unsigned int dsize = 0;
- unsigned int used_size = 0;
- void *buf = NULL;
- handle = (pims_ipc_data_t *)data;
-
- if (handle->created == 1)
- {
- ERROR("This handle is create mode.");
- return NULL;
- }
- if (handle->buf_size == 0)
- {
- ERROR("Remain buffer size is 0.");
- return NULL;
- }
- if (handle->flags & PIMS_IPC_DATA_FLAGS_WITH_TYPE)
- {
- ERROR("Not without-type mode");
- return NULL;
- }
-
- dsize = *(int*)(handle->pos);
- buf = (handle->pos+sizeof(int));
-
- if (dsize == 0) // current position is next size field becasue data size is 0
- buf = NULL;
-
- used_size = _get_used_size(dsize);
- handle->pos += used_size;
- handle->buf_size -= used_size;
- handle->free_size += used_size;
-
- VERBOSE("data get size [%u] data[%p]", dsize, buf);
- *size = dsize;
- return buf;
-}
+ // ENTER();
+ int ret = -1;
+ pims_ipc_data_s *handle = NULL;
-API void* pims_ipc_data_get_dup(pims_ipc_data_h data, unsigned int *size)
-{
- void *buf = NULL;
-
- buf = pims_ipc_data_get(data, size);
- return g_memdup(buf, *size);
-}
-
-
-API int pims_ipc_data_put_with_type(pims_ipc_data_h data, pims_ipc_data_type_e type, void *buf, unsigned int size)
-{
- pims_ipc_data_t *handle = NULL;
- unsigned int dsize = 0;
- unsigned int used_size = 0;
- handle = (pims_ipc_data_t *)data;
-
- if (handle->created == 0)
- {
- ERROR("This handle isn't create mode.");
- return -1;
- }
- if (!(handle->flags & PIMS_IPC_DATA_FLAGS_WITH_TYPE))
- {
- ERROR("Not with-type mode");
- return -1;
- }
-
- switch(type)
- {
- case PIMS_IPC_DATA_TYPE_CHAR:
- dsize = sizeof(char);
- break;
- case PIMS_IPC_DATA_TYPE_UCHAR:
- dsize = sizeof(unsigned char);
- break;
- case PIMS_IPC_DATA_TYPE_INT:
- dsize = sizeof(int);
- break;
- case PIMS_IPC_DATA_TYPE_UINT:
- dsize = sizeof(unsigned int);
- break;
- case PIMS_IPC_DATA_TYPE_LONG:
- dsize = sizeof(long);
- break;
- case PIMS_IPC_DATA_TYPE_ULONG:
- dsize = sizeof(unsigned long);
- break;
- case PIMS_IPC_DATA_TYPE_FLOAT:
- dsize = sizeof(float);
- break;
- case PIMS_IPC_DATA_TYPE_DOUBLE:
- dsize = sizeof(double);
- break;
- case PIMS_IPC_DATA_TYPE_STRING:
- if (buf == NULL)
- {
- dsize = 0;
- }
- else
- {
- dsize = strlen(buf) +1;
- }
- break;
- case PIMS_IPC_DATA_TYPE_MEMORY:
- dsize = size;
- break;
- default:
- dsize = 0;
- break;
- }
-
- if (dsize != 0 && buf == NULL)
- return -1;
-
- if (buf == NULL && dsize == 0 && type != PIMS_IPC_DATA_TYPE_STRING)
- return -1;
-
- if (handle->free_size < _get_used_size_with_type(dsize))
- {
- int new_size = 0;
- new_size = handle->alloc_size * 2;
-
- while (new_size < handle->buf_size + _get_used_size_with_type(dsize))
- new_size *= 2;
- handle->buf = g_realloc(handle->buf, new_size);
- handle->alloc_size = new_size;
- handle->free_size = handle->alloc_size - handle->buf_size;
-
- handle->pos = handle->buf;
- handle->pos += handle->buf_size;
-
- VERBOSE("free_size [%d] dsize [%d]", handle->free_size, dsize);
- }
-
- *(int*)(handle->pos) = type;
- *(int*)(handle->pos+sizeof(int)) = dsize;
- if (dsize > 0 && buf != NULL)
- memcpy((handle->pos+sizeof(int)*2), buf, dsize);
-
- used_size = _get_used_size_with_type(dsize);
- handle->pos += used_size;
- handle->buf_size += used_size;
- handle->free_size -= used_size;
-
- VERBOSE("data put type [%d] size [%u] data[%p]", type, dsize, buf);
-
- return 0;
-}
+ handle = calloc(1, sizeof(pims_ipc_data_s));
+ handle->alloc_size = size;
+ handle->free_size = size;
+ handle->buf_size = 0;
+ handle->buf = calloc(1, size);
+ handle->pos = handle->buf;
+ handle->created = 1;
+ handle->buf_alloced = 1;
-API void* pims_ipc_data_get_with_type(pims_ipc_data_h data, pims_ipc_data_type_e *type, unsigned int *size)
-{
- pims_ipc_data_t *handle = NULL;
- pims_ipc_data_type_e dtype = PIMS_IPC_DATA_TYPE_INVALID;
- unsigned int dsize = 0;
- unsigned int used_size = 0;
- void *buf = NULL;
- handle = (pims_ipc_data_t *)data;
-
- if (handle->created == 1)
- {
- ERROR("This handle is create mode.");
- *type = PIMS_IPC_DATA_TYPE_INVALID;
- return NULL;
- }
- if (handle->buf_size == 0)
- {
- ERROR("Remain buffer size is 0.");
- *type = PIMS_IPC_DATA_TYPE_INVALID;
- return NULL;
- }
- if (!(handle->flags & PIMS_IPC_DATA_FLAGS_WITH_TYPE))
- {
- ERROR("Not with-type mode");
- *type = PIMS_IPC_DATA_TYPE_INVALID;
- return NULL;
- }
-
- dtype = *(int*)(handle->pos);
- dsize = *(int*)(handle->pos+sizeof(int));
- buf = (handle->pos+sizeof(int)*2);
-
- switch(dtype)
- {
- case PIMS_IPC_DATA_TYPE_CHAR:
- case PIMS_IPC_DATA_TYPE_UCHAR:
- case PIMS_IPC_DATA_TYPE_INT:
- case PIMS_IPC_DATA_TYPE_UINT:
- case PIMS_IPC_DATA_TYPE_LONG:
- case PIMS_IPC_DATA_TYPE_ULONG:
- case PIMS_IPC_DATA_TYPE_FLOAT:
- case PIMS_IPC_DATA_TYPE_DOUBLE:
- case PIMS_IPC_DATA_TYPE_STRING:
- case PIMS_IPC_DATA_TYPE_MEMORY:
- break;
- default:
- ERROR("Unknown data type");
- dsize = 0;
- break;
- }
-
- if (dtype != PIMS_IPC_DATA_TYPE_STRING && dsize == 0)
- {
- *type = PIMS_IPC_DATA_TYPE_INVALID;
- return NULL;
- }
-
- if (dsize == 0) // current position is next type field becasue data size is 0
- buf = NULL;
-
- used_size = _get_used_size_with_type(dsize);
- handle->pos += used_size;
- handle->buf_size -= used_size;
- handle->free_size += used_size;
-
- VERBOSE("data get type [%d] size [%u] data[%p]", dtype, dsize, buf);
- *type = dtype;
- *size = dsize;
- return buf;
-}
+ ret = pims_ipc_data_put(handle, &flags, sizeof(int));
-API void* pims_ipc_data_get_dup_with_type(pims_ipc_data_h data, pims_ipc_data_type_e *type, unsigned int *size)
-{
- void *buf = NULL;
+ ASSERT(ret == 0);
+ handle->flags = flags;
- buf = pims_ipc_data_get_with_type(data, type, size);
- return g_memdup(buf, *size);
+ return handle;
}
-API void* pims_ipc_data_marshal(pims_ipc_data_h data, unsigned int *size)
+API void pims_ipc_data_destroy(pims_ipc_data_h data)
{
- pims_ipc_data_t *handle = NULL;
-
- if (!data || !size )
- return NULL;
-
- handle = (pims_ipc_data_t *)data;
+ // ENTER();
+ pims_ipc_data_s *handle = (pims_ipc_data_s *)data;
+ if (!handle)
+ return;
- *size = handle->buf_size;
+ if (handle->buf_alloced)
+ free(handle->buf);
- return handle->buf;
-}
-
-static void __pims_ipc_data_free_cb(void *data, void *hint)
-{
- if (hint)
- g_free(hint);
-}
-
-API int pims_ipc_data_marshal_with_zmq(pims_ipc_data_h data, zmq_msg_t *pzmsg)
-{
- pims_ipc_data_t *handle = NULL;
-
- if (!data || !pzmsg )
- return -1;
-
- handle = (pims_ipc_data_t *)data;
-
- if (handle->zmsg_alloced)
- {
- // TODO: need to prevent memory leackage when reusing data marshaled
- WARNING("It's ever been marshaled");
- }
-
- zmq_msg_init_data(&handle->zmsg, handle->buf, handle->buf_size, __pims_ipc_data_free_cb, handle->buf);
-
- if (zmq_msg_copy(pzmsg, &handle->zmsg) != 0)
- {
- zmq_msg_close(&handle->zmsg);
- return -1;
- }
-
- handle->zmsg_alloced = 1;
- handle->buf_alloced = 0;
-
- return 0;
+ free(handle);
}
-API void* pims_ipc_data_marshal_dup(pims_ipc_data_h data, unsigned int *size)
+API int pims_ipc_data_put(pims_ipc_data_h data, void *buf, unsigned int size)
{
- unsigned int lsize = 0;
- gpointer buf = NULL;
-
- if (!data || !size )
- return NULL;
-
- buf = pims_ipc_data_marshal(data, &lsize);
- *size = lsize;
- return g_memdup(buf, lsize);
+ // ENTER();
+ pims_ipc_data_s *handle = NULL;
+ unsigned int dsize = size;
+ unsigned int used_size = 0;
+ handle = (pims_ipc_data_s *)data;
+
+ if (handle->created == 0) {
+ ERROR("This handle isn't create mode.");
+ return -1;
+ }
+
+ if (handle->flags & PIMS_IPC_DATA_FLAGS_WITH_TYPE) {
+ ERROR("Not without-type mode");
+ return -1;
+ }
+
+ if (dsize > 0 && buf == NULL) {
+ ERROR("Invalid argument");
+ return -1;
+ }
+
+ used_size = _get_used_size(dsize);
+ if (handle->free_size < used_size) {
+ int new_size = 0;
+ new_size = handle->alloc_size * 2;
+
+ while (new_size < handle->buf_size + used_size)
+ new_size *= 2;
+ handle->buf = realloc(handle->buf, new_size);
+ handle->alloc_size = new_size;
+ handle->free_size = handle->alloc_size - handle->buf_size;
+ handle->pos = handle->buf;
+ handle->pos += handle->buf_size;
+ VERBOSE("free_size [%d] dsize [%d]", handle->free_size, dsize);
+ }
+
+ *(int*)(handle->pos) = dsize;
+ if (dsize > 0) {
+ memcpy((handle->pos+sizeof(int)), buf, dsize);
+ int pad_size = used_size-dsize-sizeof(int);
+ if (pad_size > 0)
+ memset((handle->pos+sizeof(int)+dsize), 0x0, pad_size);
+ }
+
+ handle->pos += used_size;
+ handle->buf_size += used_size;
+ handle->free_size -= used_size;
+
+ VERBOSE("data put size [%u] data[%p]", dsize, buf);
+
+ return 0;
}
-API pims_ipc_data_h pims_ipc_data_unmarshal(void *buf, unsigned int size)
+API void* pims_ipc_data_get(pims_ipc_data_h data, unsigned int *size)
{
- pims_ipc_data_t *handle = NULL;
- zmq_msg_t zmsg;
-
- zmq_msg_init_data(&zmsg, buf, size, __pims_ipc_data_free_cb, NULL);
-
- handle = pims_ipc_data_unmarshal_with_zmq(&zmsg);
- zmq_msg_close(&zmsg);
-
- return handle;
+ // ENTER();
+ pims_ipc_data_s *handle = NULL;
+ unsigned int dsize = 0;
+ unsigned int used_size = 0;
+ void *buf = NULL;
+ handle = (pims_ipc_data_s *)data;
+
+ if (handle->created == 1) {
+ ERROR("This handle is create mode.");
+ return NULL;
+ }
+ if (handle->buf_size == 0) {
+ ERROR("Remain buffer size is 0.");
+ return NULL;
+ }
+ if (handle->flags & PIMS_IPC_DATA_FLAGS_WITH_TYPE) {
+ ERROR("Not without-type mode");
+ return NULL;
+ }
+
+ dsize = *(int*)(handle->pos);
+ buf = (handle->pos+sizeof(int));
+
+ if (dsize == 0) // current position is next size field becasue data size is 0
+ buf = NULL;
+
+ used_size = _get_used_size(dsize);
+ handle->pos += used_size;
+ handle->buf_size -= used_size;
+ handle->free_size += used_size;
+
+ VERBOSE("data get size [%u] data[%p]", dsize, buf);
+ *size = dsize;
+ return buf;
}
-API pims_ipc_data_h pims_ipc_data_unmarshal_with_zmq(zmq_msg_t *pzmsg)
-{
- pims_ipc_data_t *handle = NULL;
- unsigned int size = 0;
- void *ptr = NULL;
-
- handle = g_new0(pims_ipc_data_t, 1);
- zmq_msg_init(&handle->zmsg);
- if (zmq_msg_copy(&handle->zmsg, pzmsg) != 0)
- {
- g_free(handle);
- return NULL;
- }
- handle->alloc_size = zmq_msg_size(&handle->zmsg);
- handle->free_size = 0;
- handle->buf_size = handle->alloc_size;
- handle->buf = zmq_msg_data(&handle->zmsg);
- handle->pos = handle->buf;
- handle->created = 0;
- handle->zmsg_alloced = 1;
-
- ptr = pims_ipc_data_get(handle, &size);
- if (!ptr || size != sizeof(int))
- {
- g_free(handle);
- return NULL;
- }
- handle->flags = *((int*)ptr);
-
- VERBOSE("handle[%p] zmsg[%p] flags[%x]", handle, pzmsg, handle->flags);
-
- return handle;
+pims_ipc_data_h pims_ipc_data_steal_unmarshal(void *buf, unsigned int size)
+{
+ // ENTER();
+ void *ptr = NULL;
+ pims_ipc_data_s *handle = NULL;
+
+ VERBOSE("size : %d", size);
+ handle = calloc(1, sizeof(pims_ipc_data_s));
+ handle->alloc_size = size;
+ handle->free_size = 0;
+ handle->buf_size = handle->alloc_size;
+ handle->buf = buf;
+ handle->pos = handle->buf;
+ handle->created = 0;
+ handle->buf_alloced = 1;
+
+ ptr = pims_ipc_data_get(handle, &size);
+ if (!ptr || size != sizeof(int)) {
+ ERROR("pims_ipc_data_get : error");
+ free(handle->buf);
+ free(handle);
+ return NULL;
+ }
+ handle->flags = *((int*)ptr);
+
+ VERBOSE("handle[%p] flags[%x]", handle, handle->flags);
+
+ return handle;
}
-API pims_ipc_data_h pims_ipc_data_unmarshal_dup(void *buf, unsigned int size)
-{
- pims_ipc_data_t *handle = NULL;
- zmq_msg_t zmsg;
-
- zmq_msg_init_size(&zmsg, size);
- memcpy(zmq_msg_data(&zmsg), buf, size);
-
- handle = pims_ipc_data_unmarshal_with_zmq(&zmsg);
- zmq_msg_close(&zmsg);
-
- return handle;
-}
#include <glib.h>
#include <pthread.h>
#include <stdint.h>
-#include <sys/types.h>
+#include <poll.h> // pollfds
+#include <fcntl.h> //fcntl
+#include <unistd.h>
+#include <systemd/sd-daemon.h>
+
#include <sys/stat.h>
+#include <sys/un.h> // sockaddr_un
+#include <sys/ioctl.h> // ioctl
+#include <sys/epoll.h> // epoll
+#include <sys/eventfd.h> // eventfd
+#include <sys/socket.h> //socket
+#include <sys/types.h>
-#include <pims-internal.h>
-#include <pims-debug.h>
-#include <pims-socket.h>
-#include <pims-ipc-data.h>
-#include <pims-ipc-svc.h>
+#include "pims-internal.h"
+#include "pims-debug.h"
+#include "pims-socket.h"
+#include "pims-ipc-data.h"
+#include "pims-ipc-data-internal.h"
+#include "pims-ipc-svc.h"
#define PIMS_IPC_WORKERS_DEFAULT_MAX_COUNT 2
-typedef struct
-{
- char *service;
- gid_t group;
- mode_t mode;
- GHashTable *cb_table;
- GHashTable *client_table;
- GList *workers;
- GList *requests;
- int workers_max_count;
- void* context;
- void* router;
- void* worker;
- void* manager;
- void* monitor;
-} pims_ipc_svc_t;
-
-typedef struct
-{
- char *service;
- gid_t group;
- mode_t mode;
- void* context;
- void* publisher;
-} pims_ipc_svc_for_publish_t;
-
-
-typedef struct
+typedef struct {
+ char *service;
+ gid_t group;
+ mode_t mode;
+
+ // callback functions
+ GHashTable *cb_table; // call_id, cb_data
+
+ // Global socket info and epoll thread
+ int sockfd;
+ bool epoll_stop_thread;
+
+ /////////////////////////////////////////////
+ // router inproc eventfd
+ int router;
+ int delay_count; // not need mutex
+ // epoll thread add client_fd, when receive, router read requests
+ GList *request_queue; // client_id lists to send request
+ pthread_mutex_t request_data_queue_mutex;
+ GHashTable *request_data_queue; // key : client id, data : GList pims_ipc_raw_data_s (client_fd, seq_no, request(command), additional data...)
+ // router add client when receive connecting request, remove client when disconneting request in router thread
+ // manager remove client when terminating client without disconnect request in router thread
+ GHashTable *client_worker_map; // key : client_id, worker_fd, not need mutex
+ GList *client_id_fd_map; // pims_ipc_client_map_s
+ //key :client_id(pid:seq_no), data : client_fd
+
+ /////////////////////////////////////////////
+ pthread_mutex_t task_fds_mutex;
+ // when starting worker thread, register fd
+ // when endting worker thread, deregister fd
+ GHashTable *task_fds; // worker_fd - worker data (worker fd, client_fd, request queue(GList), stop_thread)
+ int workers_max_count;
+
+ /////////////////////////////////////////////
+ // manager inproc eventfd
+ int manager;
+ // write by new worker thread, read by manager in router thread, need mutex
+ pthread_mutex_t manager_queue_from_worker_mutex;
+ GList *manager_queue_from_worker; // worker_fd => add to workers
+ // write in epoll thread(for dead client), read by manager in router thread, need mutex
+ pthread_mutex_t manager_queue_from_epoll_mutex;
+ GList *manager_queue_from_epoll; // cliend_fd => find worker_fd => add to idle workers
+ // managed by manager, router find idle worker when connecting new client in router thread => remove from idle workers
+ GList *workers; // worker_fd list, not need mutex
+ /////////////////////////////////////////////
+} pims_ipc_svc_s;
+
+typedef struct {
+ char *service;
+ gid_t group;
+ mode_t mode;
+
+ int publish_sockfd;
+ bool epoll_stop_thread;
+ pthread_mutex_t subscribe_fds_mutex;
+ GList *subscribe_fds; // cliend fd list
+} pims_ipc_svc_for_publish_s;
+
+typedef struct {
+ int fd;
+ char *id;
+}pims_ipc_client_map_s;
+
+typedef struct {
+ pims_ipc_svc_call_cb callback;
+ void * user_data;
+} pims_ipc_svc_cb_s;
+
+typedef struct {
+ pims_ipc_svc_client_disconnected_cb callback;
+ void * user_data;
+} pims_ipc_svc_client_disconnected_cb_t;
+
+typedef struct {
+ int fd;
+ int worker_id; // pthrad_self()
+ int client_fd;
+ bool stop_thread;
+ GList *queue; // pims_ipc_raw_data_s list
+ pthread_mutex_t queue_mutex;
+} pims_ipc_worker_data_s;
+
+typedef struct{
+ char *client_id;
+ unsigned int client_id_len;
+ unsigned int seq_no;
+ char *call_id;
+ unsigned int call_id_len;
+ unsigned int is_data;
+ unsigned int data_len;
+ char *data;
+}pims_ipc_raw_data_s;
+
+typedef struct {
+ int client_fd;
+ int request_count;
+ GList *raw_data; // pims_ipc_raw_data_s list
+ pthread_mutex_t raw_data_mutex;
+}pims_ipc_request_s;
+
+static pims_ipc_svc_s *_g_singleton = NULL;
+static pims_ipc_svc_for_publish_s *_g_singleton_for_publish = NULL;
+
+static __thread pims_ipc_svc_client_disconnected_cb_t _client_disconnected_cb = {NULL, NULL};
+
+static void __free_raw_data(pims_ipc_raw_data_s *data)
{
- pims_ipc_svc_call_cb callback;
- void * user_data;
-} pims_ipc_svc_cb_t;
+ if (!data) return;
-static pims_ipc_svc_t *_g_singleton = NULL;
-static pims_ipc_svc_for_publish_t *_g_singleton_for_publish = NULL;
-
-#define PIMS_IPC_STRING_WORKER_ID_SIZE 10
-static char* __get_string_worker_id(int worker_id, char *string_worker_id)
-{
- snprintf(string_worker_id, PIMS_IPC_STRING_WORKER_ID_SIZE, "%08x00", worker_id);
- string_worker_id[PIMS_IPC_STRING_WORKER_ID_SIZE] = 0x0;
-
- return string_worker_id;
+ free(data->client_id);
+ free(data->call_id);
+ free(data->data);
+ free(data);
}
-API int pims_ipc_svc_init(char *service, gid_t group, mode_t mode)
+static void __worker_data_free(gpointer data)
{
- if (_g_singleton)
- {
- ERROR("Already exist");
- return -1;
- }
-
- _g_singleton = g_new0(pims_ipc_svc_t, 1);
- _g_singleton->service = g_strdup(service);
- _g_singleton->group = group;
- _g_singleton->mode = mode;
- _g_singleton->workers_max_count = PIMS_IPC_WORKERS_DEFAULT_MAX_COUNT;
- _g_singleton->cb_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
- ASSERT(_g_singleton->cb_table);
- _g_singleton->client_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
- ASSERT(_g_singleton->client_table);
-
- return 0;
+ pims_ipc_worker_data_s *worker_data = (pims_ipc_worker_data_s*)data;
+
+ pthread_mutex_lock(&worker_data->queue_mutex);
+ if (worker_data->queue) {
+ GList *cursor = g_list_first(worker_data->queue);
+ while(cursor) {
+ GList *l = cursor;
+ pims_ipc_raw_data_s *data = l->data;
+ cursor = g_list_next(cursor);
+ worker_data->queue = g_list_remove_link(worker_data->queue, l);
+ g_list_free(l);
+ __free_raw_data(data);
+ }
+ }
+ pthread_mutex_unlock(&worker_data->queue_mutex);
+ free(worker_data);
}
-static void __free_zmq_msg(gpointer data)
+API int pims_ipc_svc_init(char *service, gid_t group, mode_t mode)
{
- zmq_msg_t *lpzmsg = data;
-
- if (lpzmsg)
- {
- zmq_msg_close(lpzmsg);
- g_free(lpzmsg);
- }
+ if (_g_singleton) {
+ ERROR("Already exist");
+ return -1;
+ }
+
+ _g_singleton = g_new0(pims_ipc_svc_s, 1);
+ _g_singleton->service = g_strdup(service);
+ _g_singleton->group = group;
+ _g_singleton->mode = mode;
+ _g_singleton->workers_max_count = PIMS_IPC_WORKERS_DEFAULT_MAX_COUNT;
+ _g_singleton->cb_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ ASSERT(_g_singleton->cb_table);
+
+ pthread_mutex_init(&_g_singleton->request_data_queue_mutex, 0);
+ _g_singleton->request_queue = NULL;
+ _g_singleton->request_data_queue = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); // client_id - pims_ipc_raw_data_s
+ ASSERT(_g_singleton->request_data_queue);
+ _g_singleton->client_worker_map = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); // client id - worker_fd mapping
+ ASSERT(_g_singleton->client_worker_map);
+ _g_singleton->delay_count = 0;
+
+ pthread_mutex_init(&_g_singleton->task_fds_mutex, 0);
+ _g_singleton->task_fds = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, __worker_data_free); // pims_ipc_worker_data_s
+ ASSERT(_g_singleton->task_fds);
+
+ pthread_mutex_init(&_g_singleton->manager_queue_from_epoll_mutex, 0);
+ _g_singleton->manager_queue_from_epoll = NULL;
+
+ pthread_mutex_init(&_g_singleton->manager_queue_from_worker_mutex, 0);
+ _g_singleton->manager_queue_from_worker = NULL;
+ _g_singleton->workers = NULL;
+
+ _g_singleton->epoll_stop_thread = false;
+
+ return 0;
}
API int pims_ipc_svc_deinit(void)
{
- if (!_g_singleton)
- return -1;
-
- g_free(_g_singleton->service);
- g_hash_table_destroy(_g_singleton->cb_table);
- g_hash_table_destroy(_g_singleton->client_table);
- g_list_free(_g_singleton->workers);
- g_list_free_full(_g_singleton->requests, __free_zmq_msg);
- g_free(_g_singleton);
- _g_singleton = NULL;
-
- return 0;
+ if (!_g_singleton)
+ return -1;
+
+ g_free(_g_singleton->service);
+ g_hash_table_destroy(_g_singleton->cb_table);
+
+ pthread_mutex_destroy(&_g_singleton->request_data_queue_mutex);
+ g_hash_table_destroy(_g_singleton->client_worker_map);
+ g_hash_table_destroy(_g_singleton->request_data_queue);
+ g_list_free_full(_g_singleton->request_queue, g_free);
+
+ pthread_mutex_destroy(&_g_singleton->task_fds_mutex);
+ g_hash_table_destroy(_g_singleton->task_fds);
+
+ pthread_mutex_destroy(&_g_singleton->manager_queue_from_epoll_mutex);
+ g_list_free_full(_g_singleton->manager_queue_from_epoll, g_free);
+ pthread_mutex_destroy(&_g_singleton->manager_queue_from_worker_mutex);
+ g_list_free(_g_singleton->manager_queue_from_worker);
+
+ GList *cursor = g_list_first(_g_singleton->client_id_fd_map);
+ while(cursor) {
+ pims_ipc_client_map_s *client = cursor->data;
+ _g_singleton->client_id_fd_map = g_list_remove_link(_g_singleton->client_id_fd_map, cursor); //free(client_id);
+ free(client->id);
+ free(client);
+ g_list_free(cursor);
+ cursor = g_list_first(_g_singleton->client_id_fd_map);
+ }
+ g_list_free(_g_singleton->client_id_fd_map);
+
+ g_list_free(_g_singleton->workers);
+ g_free(_g_singleton);
+ _g_singleton = NULL;
+
+ return 0;
}
API int pims_ipc_svc_register(char *module, char *function, pims_ipc_svc_call_cb callback, void *userdata)
{
- pims_ipc_svc_cb_t *cb_data = NULL;
- gchar *call_id = NULL;
-
- if (!module || !function || !callback)
- {
- ERROR("Invalid argument");
- return -1;
- }
- cb_data = g_new0(pims_ipc_svc_cb_t, 1);
- call_id = PIMS_IPC_MAKE_CALL_ID(module, function);
-
- VERBOSE("register cb id[%s]", call_id);
- cb_data->callback = callback;
- cb_data->user_data = userdata;
- g_hash_table_insert(_g_singleton->cb_table, call_id, cb_data);
-
- return 0;
+ pims_ipc_svc_cb_s *cb_data = NULL;
+ gchar *call_id = NULL;
+
+ if (!module || !function || !callback) {
+ ERROR("Invalid argument");
+ return -1;
+ }
+ cb_data = g_new0(pims_ipc_svc_cb_s, 1);
+ call_id = PIMS_IPC_MAKE_CALL_ID(module, function);
+
+ VERBOSE("register cb id[%s]", call_id);
+ cb_data->callback = callback;
+ cb_data->user_data = userdata;
+ g_hash_table_insert(_g_singleton->cb_table, call_id, cb_data);
+
+ return 0;
}
API int pims_ipc_svc_init_for_publish(char *service, gid_t group, mode_t mode)
{
- if (_g_singleton_for_publish)
- {
- ERROR("Already exist");
- return -1;
- }
-
- _g_singleton_for_publish = g_new0(pims_ipc_svc_for_publish_t, 1);
- _g_singleton_for_publish->service = g_strdup(service);
- _g_singleton_for_publish->group = group;
- _g_singleton_for_publish->mode = mode;
-
- return 0;
+ if (_g_singleton_for_publish) {
+ ERROR("Already exist");
+ return -1;
+ }
+
+ _g_singleton_for_publish = g_new0(pims_ipc_svc_for_publish_s, 1);
+ _g_singleton_for_publish->service = g_strdup(service);
+ _g_singleton_for_publish->group = group;
+ _g_singleton_for_publish->mode = mode;
+ _g_singleton_for_publish->subscribe_fds = NULL;
+
+ pthread_mutex_init(&_g_singleton_for_publish->subscribe_fds_mutex, 0);
+
+ return 0;
}
API int pims_ipc_svc_deinit_for_publish(void)
{
- if (!_g_singleton_for_publish)
- return -1;
+ if (!_g_singleton_for_publish)
+ return -1;
- g_free(_g_singleton_for_publish->service);
- g_free(_g_singleton_for_publish);
- _g_singleton_for_publish = NULL;
+ pthread_mutex_destroy(&_g_singleton_for_publish->subscribe_fds_mutex);
+ g_list_free(_g_singleton_for_publish->subscribe_fds);
- return 0;
-}
+ g_free(_g_singleton_for_publish->service);
+ g_free(_g_singleton_for_publish);
+ _g_singleton_for_publish = NULL;
-static void __pims_ipc_svc_data_free_cb(void *data, void *hint)
-{
- if (hint)
- g_free(hint);
+ return 0;
}
API int pims_ipc_svc_publish(char *module, char *event, pims_ipc_data_h data)
{
- pims_ipc_svc_for_publish_t *ipc_svc = _g_singleton_for_publish;
- gboolean is_valid = FALSE;
- gchar *call_id = PIMS_IPC_MAKE_CALL_ID(module, event);
-
- // init messages
- zmq_msg_t call_id_msg;
- zmq_msg_t data_msg;
-
- zmq_msg_init_data(&call_id_msg, call_id, strlen(call_id) + 1, __pims_ipc_svc_data_free_cb, call_id);
- VERBOSE("call id = %s", (char*)zmq_msg_data(&call_id_msg));
-
- zmq_msg_init(&data_msg);
-
- do {
- if (data == NULL)
- {
- // send call id
- if (_pims_zmq_msg_send(&call_id_msg, ipc_svc->publisher, 0) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- break;
- }
- }
- else
- {
- // send call id
- if (_pims_zmq_msg_send(&call_id_msg, ipc_svc->publisher, ZMQ_SNDMORE) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- break;
- }
-
- // marshal data
- if (pims_ipc_data_marshal_with_zmq(data, &data_msg) != 0)
- {
- ERROR("marshal error");
- break;
- }
-
- VERBOSE("the size of sending data = %d", zmq_msg_size(&data_msg));
-
- // send data
- if (_pims_zmq_msg_send(&data_msg, ipc_svc->publisher, 0) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- break;
- }
- }
-
- is_valid = TRUE;
- } while (0);
-
- zmq_msg_close(&call_id_msg);
- zmq_msg_close(&data_msg);
-
- if (is_valid == FALSE)
- return -1;
- return 0;
+ pims_ipc_svc_for_publish_s *ipc_svc = _g_singleton_for_publish;
+ gboolean is_valid = FALSE;
+ gchar *call_id = PIMS_IPC_MAKE_CALL_ID(module, event);
+ pims_ipc_data_s *data_in = (pims_ipc_data_s*)data;
+ unsigned int call_id_len = strlen(call_id);
+ unsigned int is_data = FALSE;
+
+ do {
+ // make publish data
+ unsigned int len = sizeof(unsigned int) // total size
+ + call_id_len + sizeof(unsigned int) // call_id
+ + sizeof(unsigned int); // is data
+ unsigned int total_len = len;
+
+ if (data_in) {
+ is_data = TRUE;
+ len += sizeof(unsigned int);
+ total_len = len + data_in->buf_size; // data
+ }
+
+ char buf[len+1];
+ int length = 0;
+ memset(buf, 0x0, len+1);
+
+ // total_size
+ memcpy(buf, (void*)&total_len, sizeof(unsigned int));
+ length += sizeof(unsigned int);
+
+ // call_id
+ memcpy(buf+length, (void*)&(call_id_len), sizeof(unsigned int));
+ length += sizeof(unsigned int);
+ memcpy(buf+length, (void*)(call_id), call_id_len);
+ length += call_id_len;
+ g_free(call_id);
+
+ // is_data
+ memcpy(buf+length, (void*)&(is_data), sizeof(unsigned int));
+ length += sizeof(unsigned int);
+
+ // data
+ if (is_data) {
+ memcpy(buf+length, (void*)&(data_in->buf_size), sizeof(unsigned int));
+ length += sizeof(unsigned int);
+ }
+
+ // Publish to clients
+ pthread_mutex_lock(&ipc_svc->subscribe_fds_mutex);
+ GList *cursor = g_list_first(ipc_svc->subscribe_fds);
+ int ret = 0;
+ while(cursor) {
+ int fd = (int)cursor->data;
+ ret = socket_send(fd, buf, length);
+ if (ret < 0) {
+ ERROR("socket_send publish error : %d", ret);
+ }
+
+ if (is_data) {
+ ret = socket_send_data(fd, data_in->buf, data_in->buf_size);
+ if (ret < 0) {
+ ERROR("socket_send_data publish error : %d", ret);
+ }
+ }
+ cursor = g_list_next(cursor);
+ }
+ pthread_mutex_unlock(&ipc_svc->subscribe_fds_mutex);
+
+ is_valid = TRUE;
+ } while (0);
+
+ if (is_valid == FALSE)
+ return -1;
+ return 0;
}
static void __run_callback(int worker_id, char *call_id, pims_ipc_data_h dhandle_in, pims_ipc_data_h *dhandle_out)
{
- pims_ipc_svc_cb_t *cb_data = NULL;
-
- VERBOSE("Call id [%s]", call_id);
-
- cb_data = (pims_ipc_svc_cb_t*)g_hash_table_lookup(_g_singleton->cb_table, call_id);
- if (cb_data == NULL)
- {
- VERBOSE("unable to find %s", call_id);
- return;
- }
-
- cb_data->callback((pims_ipc_h)worker_id, dhandle_in, dhandle_out, cb_data->user_data);
+ pims_ipc_svc_cb_s *cb_data = NULL;
+
+ VERBOSE("Call id [%s]", call_id);
+
+ cb_data = (pims_ipc_svc_cb_s*)g_hash_table_lookup(_g_singleton->cb_table, call_id);
+ if (cb_data == NULL) {
+ VERBOSE("unable to find %s", call_id);
+ return;
+ }
+
+ cb_data->callback((pims_ipc_h)worker_id, dhandle_in, dhandle_out, cb_data->user_data);
+}
+
+static void __make_raw_data(const char *call_id, int seq_no, pims_ipc_data_h data, pims_ipc_raw_data_s**out)
+{
+ pims_ipc_raw_data_s *raw_data = NULL;
+ raw_data = (pims_ipc_raw_data_s*)calloc(1, sizeof(pims_ipc_raw_data_s));
+ pims_ipc_data_s *data_in = (pims_ipc_data_s*)data;
+
+ raw_data->call_id = strdup(call_id);
+ raw_data->call_id_len = strlen(raw_data->call_id);
+ raw_data->seq_no = seq_no;
+
+ if (data_in && data_in->buf_size > 0) {
+ raw_data->is_data = TRUE;
+ raw_data->data = calloc(1, data_in->buf_size+1);
+ memcpy(raw_data->data, data_in->buf, data_in->buf_size);
+ raw_data->data_len = data_in->buf_size;
+ }
+ else {
+ raw_data->is_data = FALSE;
+ raw_data->data_len = 0;
+ raw_data->data = NULL;
+ }
+ *out = raw_data;
+ return;
}
-static int __process_worker_task(int worker_id, void *context, void *worker)
+static int __send_raw_data(int fd, const char *client_id, pims_ipc_raw_data_s *data)
{
- gboolean is_create = FALSE;
- gboolean is_destroy = FALSE;
- char *pid = NULL;
- char *call_id = NULL;
- int64_t more = 0;
- size_t more_size = sizeof(more);
- pims_ipc_data_h dhandle_in = NULL;
- pims_ipc_data_h dhandle_out = NULL;
-
- VERBOSE("");
-
-#ifdef _TEST
- struct timeval tv;
- gettimeofday(&tv, NULL);
- printf("worker time[%lu:%lu]\n", tv.tv_sec, tv.tv_usec);
-#endif
-
- zmq_msg_t pid_msg;
- zmq_msg_t sequence_no_msg;
- zmq_msg_t call_id_msg;
- zmq_msg_t data_msg;
-
- zmq_msg_init(&pid_msg);
- zmq_msg_init(&sequence_no_msg);
- zmq_msg_init(&call_id_msg);
- zmq_msg_init(&data_msg);
-
- do {
- // read pid
- if (_pims_zmq_msg_recv(&pid_msg, worker, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- break;
- }
-
- // read sequence no
- if (_pims_zmq_msg_recv(&sequence_no_msg, worker, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- break;
- }
-
- // read call id
- if (_pims_zmq_msg_recv(&call_id_msg, worker, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- break;
- }
-
- more = 0;
- zmq_getsockopt(worker, ZMQ_RCVMORE, &more, &more_size);
- if (more)
- {
- // read data
- if (_pims_zmq_msg_recv(&data_msg, worker, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- break;
- }
-
- dhandle_in = pims_ipc_data_unmarshal_with_zmq(&data_msg);
- if (dhandle_in == NULL)
- {
- ERROR("unmarshal error");
- break;
- }
- }
-
- pid = (char*)zmq_msg_data(&pid_msg);
- ASSERT(pid);
- VERBOSE("client pid = %s", pid);
-
- call_id = (char*)zmq_msg_data(&call_id_msg);
- ASSERT(call_id);
- VERBOSE("call_id = [%s]", call_id);
-
- // call a callback function with call id and data
- if (strcmp(PIMS_IPC_CALL_ID_CREATE, call_id) == 0)
- {
- is_create = TRUE;
- }
- else if (strcmp(PIMS_IPC_CALL_ID_DESTROY, call_id) == 0)
- {
- is_destroy = TRUE;
- }
- else
- {
- __run_callback(worker_id, call_id, dhandle_in, &dhandle_out);
- }
-
- // send pid
- if (_pims_zmq_msg_send(&pid_msg, worker, ZMQ_SNDMORE) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- break;
- }
-
- // send empty
- zmq_msg_t empty_msg;
- zmq_msg_init_size(&empty_msg, 0);
- if (_pims_zmq_msg_send(&empty_msg, worker, ZMQ_SNDMORE) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- zmq_msg_close(&empty_msg);
- break;
- }
- zmq_msg_close(&empty_msg);
-
- // send sequence no
- if (_pims_zmq_msg_send(&sequence_no_msg, worker, ZMQ_SNDMORE) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- break;
- }
-
- if (dhandle_out)
- {
- // send call id
- if (_pims_zmq_msg_send(&call_id_msg, worker, ZMQ_SNDMORE) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- break;
- }
-
- // marshal data
- zmq_msg_close(&data_msg);
- zmq_msg_init(&data_msg);
- if (pims_ipc_data_marshal_with_zmq(dhandle_out, &data_msg) != 0)
- {
- ERROR("marshal error");
- break;
- }
-
- // send data
- VERBOSE("the size of sending data = %d", zmq_msg_size(&data_msg));
- if (_pims_zmq_msg_send(&data_msg, worker, 0) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- break;
- }
- }
- else
- {
- // send call id
- if (_pims_zmq_msg_send(&call_id_msg, worker, 0) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- break;
- }
- }
- } while (0);
-
- zmq_msg_close(&pid_msg);
- zmq_msg_close(&sequence_no_msg);
- zmq_msg_close(&call_id_msg);
- zmq_msg_close(&data_msg);
-
- if (dhandle_in)
- pims_ipc_data_destroy(dhandle_in);
- if (dhandle_out)
- pims_ipc_data_destroy(dhandle_out);
-
- VERBOSE("responsed");
-
-#ifdef _TEST
- gettimeofday(&tv, NULL);
- printf("worker time[%lu:%lu]\n", tv.tv_sec, tv.tv_usec);
-#endif
-
- if (is_destroy)
- return -1;
- return 0;
+ int ret = 0;
+ unsigned int client_id_len = strlen(client_id);
+
+ if (!data) {
+ INFO("No data to send NULL\n");
+ return -1;
+ }
+
+ unsigned int len = sizeof(unsigned int) // total size
+ + client_id_len + sizeof(unsigned int) // client_id
+ + sizeof(unsigned int) // seq_no
+ + data->call_id_len + sizeof(unsigned int) // call_id
+ + sizeof(unsigned int); // is data
+ unsigned int total_len = len;
+
+ if (data->is_data) {
+ len += sizeof(unsigned int); // data
+ total_len = len + data->data_len; // data
+ }
+
+ INFO("client_id: %s, call_id : %s, seq no :%d, len:%d, total len :%d", client_id, data->call_id, data->seq_no, len, total_len);
+
+ char buf[len+1];
+
+ int length = 0;
+ memset(buf, 0x0, len+1);
+
+ // total_len
+ memcpy(buf, (void*)&total_len, sizeof(unsigned int));
+ length += sizeof(unsigned int);
+
+ // client_id
+ memcpy(buf+length, (void*)&(client_id_len), sizeof(unsigned int));
+ length += sizeof(unsigned int);
+ memcpy(buf+length, (void*)(client_id), client_id_len);
+ length += client_id_len;
+
+ // seq_no
+ memcpy(buf+length, (void*)&(data->seq_no), sizeof(unsigned int));
+ length += sizeof(unsigned int);
+
+ // call id
+ memcpy(buf+length, (void*)&(data->call_id_len), sizeof(unsigned int));
+ length += sizeof(unsigned int);
+ memcpy(buf+length, (void*)(data->call_id), data->call_id_len);
+ length += data->call_id_len;
+
+ // is_data
+ memcpy(buf+length, (void*)&(data->is_data), sizeof(unsigned int));
+ length += sizeof(unsigned int);
+
+ if (data->is_data) {
+ memcpy(buf+length, (void*)&(data->data_len), sizeof(unsigned int));
+ length += sizeof(unsigned int);
+ ret = socket_send(fd, buf, length);
+
+ // send data
+ if (ret > 0)
+ ret += socket_send_data(fd, data->data, data->data_len);
+ }
+ else
+ ret = socket_send(fd, buf, length);
+
+ return ret;
}
-static int __process_manager_task(int worker_id, void *context, void *manager)
+static gboolean __worker_raw_data_pop(pims_ipc_worker_data_s *worker, pims_ipc_raw_data_s **data)
{
- VERBOSE("");
-
- // read pid
- zmq_msg_t pid_msg;
- zmq_msg_init(&pid_msg);
- if (_pims_zmq_msg_recv(&pid_msg, manager, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- zmq_msg_close(&pid_msg);
- return -1;
- }
- zmq_msg_close(&pid_msg);
-
- return -1;
+ if (!worker)
+ return FALSE;
+
+ pthread_mutex_lock(&worker->queue_mutex);
+ if (!worker->queue) {
+ pthread_mutex_unlock(&worker->queue_mutex);
+ *data = NULL;
+ return FALSE;
+ }
+
+ *data = g_list_first(worker->queue)->data;
+ worker->queue = g_list_delete_link(worker->queue, g_list_first(worker->queue));
+ pthread_mutex_unlock(&worker->queue_mutex);
+
+ return TRUE;
}
-static void* __worker_loop(void *args)
+static void* __worker_loop(void *data)
{
- void *context = args;
- int worker_id = (int)pthread_self();
- char *path = NULL;
-
- void *worker = zmq_socket(context, ZMQ_DEALER);
- if (!worker)
- {
- ERROR("socket error : %s", zmq_strerror(errno));
- return NULL;
- }
- char string_worker_id[PIMS_IPC_STRING_WORKER_ID_SIZE + 1] = "";
- if (zmq_setsockopt(worker, ZMQ_IDENTITY, __get_string_worker_id(worker_id, string_worker_id),
- PIMS_IPC_STRING_WORKER_ID_SIZE) != 0)
- {
- ERROR("setsockopt error : %s", zmq_strerror(errno));
- zmq_close(worker);
- return NULL;
- }
- path = g_strdup_printf("inproc://%s-%s", _g_singleton->service, PIMS_IPC_DEALER_PATH);
- if (zmq_connect(worker, path) != 0)
- {
- ERROR("connect error : %s", zmq_strerror(errno));
- g_free(path);
- zmq_close(worker);
- return NULL;
- }
- g_free(path);
-
- // send the ID of a worker to the manager
- void *manager = zmq_socket(context, ZMQ_DEALER);
- if (!manager)
- {
- ERROR("socket error : %s", zmq_strerror(errno));
- zmq_close(worker);
- return NULL;
- }
- if (zmq_setsockopt(manager, ZMQ_IDENTITY, __get_string_worker_id(worker_id, string_worker_id),
- PIMS_IPC_STRING_WORKER_ID_SIZE) != 0)
- {
- ERROR("setsockopt error : %s", zmq_strerror(errno));
- zmq_close(manager);
- zmq_close(worker);
- return NULL;
- }
- path = g_strdup_printf("inproc://%s-%s", _g_singleton->service, PIMS_IPC_MANAGER_PATH);
- if (zmq_connect(manager, path) != 0)
- {
- ERROR("connect error : %s", zmq_strerror(errno));
- g_free(path);
- zmq_close(manager);
- zmq_close(worker);
- return NULL;
- }
- g_free(path);
-
- VERBOSE("starting worker id: %x", worker_id);
- zmq_msg_t message;
- zmq_msg_init_size(&message, sizeof(int));
- memcpy(zmq_msg_data(&message), &worker_id, sizeof(int));
- if (_pims_zmq_msg_send(&message, manager, 0) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- zmq_msg_close(&message);
- zmq_close(manager);
- zmq_close(worker);
- return NULL;
- }
- zmq_msg_close(&message);
-
- // poll all sockets
- while (1)
- {
- zmq_pollitem_t items[] = {
- {worker, 0, ZMQ_POLLIN, 0},
- {manager, 0, ZMQ_POLLIN, 0}
- };
-
- if (zmq_poll(items, 2, -1) == -1)
- {
- if (errno == EINTR)
- continue;
-
- ERROR("poll error : %s", zmq_strerror(errno));
- break;
- }
-
- if (items[0].revents & ZMQ_POLLIN)
- {
- if (__process_worker_task(worker_id, context, worker) != 0)
- break;
- }
-
- if (items[1].revents & ZMQ_POLLIN)
- {
- if (__process_manager_task(worker_id, context, manager) != 0)
- break;
- }
- }
-
- VERBOSE("terminating worker id: %x", worker_id);
-
- zmq_close(manager);
- zmq_close(worker);
- return NULL;
+ int ret;
+ int worker_id;
+ int worker_fd;
+ pims_ipc_svc_s *ipc_svc = (pims_ipc_svc_s*)data;
+ pims_ipc_worker_data_s *worker_data;
+ bool disconnected = false;
+
+ worker_fd = eventfd(0, 0);
+ if (worker_fd == -1)
+ return NULL;
+ worker_id = (int)pthread_self();
+
+ worker_data = calloc(1, sizeof(pims_ipc_worker_data_s));
+ worker_data->fd = worker_fd;
+ worker_data->worker_id = worker_id;
+ worker_data->client_fd = -1;
+ worker_data->stop_thread = false;
+ pthread_mutex_init(&worker_data->queue_mutex, 0);
+
+ pthread_mutex_lock(&ipc_svc->task_fds_mutex);
+ g_hash_table_insert(ipc_svc->task_fds, GINT_TO_POINTER(worker_fd), worker_data);
+ pthread_mutex_unlock(&ipc_svc->task_fds_mutex);
+
+ pthread_mutex_lock(&ipc_svc->manager_queue_from_worker_mutex);
+ ipc_svc->manager_queue_from_worker = g_list_append(ipc_svc->manager_queue_from_worker, (void*)worker_fd);
+ pthread_mutex_unlock(&ipc_svc->manager_queue_from_worker_mutex);
+
+ write_command(ipc_svc->manager, 1);
+ DEBUG("worker register to manager : worker_id(%08x00), worker_fd(%d)\n", worker_id, worker_fd);
+
+ struct pollfd *pollfds = (struct pollfd*) malloc (1 * sizeof (struct pollfd));
+ pollfds[0].fd = worker_fd;
+ pollfds[0].events = POLLIN;
+
+ while (!worker_data->stop_thread) {
+ while(1) {
+ if (worker_data->stop_thread)
+ break;
+ ret = poll(pollfds, 1, 3000); // waiting command from router
+ if (ret == -1 && errno == EINTR) {
+ continue;
+ }
+ break;
+ }
+
+ if (worker_data->stop_thread)
+ break;
+
+ if (ret > 0) {
+ pims_ipc_raw_data_s *raw_data = NULL;
+ pims_ipc_raw_data_s *result = NULL;
+
+ if (pollfds[0].revents & POLLIN) {
+ uint64_t dummy;
+ read_command(pollfds[0].fd, &dummy);
+ if (__worker_raw_data_pop(worker_data, &raw_data)) {
+ pims_ipc_data_h data_in = NULL;
+ pims_ipc_data_h data_out = NULL;
+
+ if (strcmp(PIMS_IPC_CALL_ID_CREATE, raw_data->call_id) == 0) {
+
+ }
+ else if (strcmp(PIMS_IPC_CALL_ID_DESTROY, raw_data->call_id) == 0) {
+ disconnected = true;
+ }
+ else {
+ data_in = pims_ipc_data_steal_unmarshal(raw_data->data, raw_data->data_len);
+ raw_data->data = NULL;
+ raw_data->data_len = 0;
+ raw_data->is_data = false;
+ __run_callback(worker_id, raw_data->call_id, data_in, &data_out);
+ pims_ipc_data_destroy(data_in);
+ }
+
+ if (data_out) {
+ __make_raw_data(raw_data->call_id, raw_data->seq_no, data_out, &result);
+ pims_ipc_data_destroy(data_out);
+ }
+ else
+ __make_raw_data(raw_data->call_id, raw_data->seq_no, NULL, &result);
+
+ if (worker_data->client_fd != -1)
+ __send_raw_data(worker_data->client_fd, raw_data->client_id, result);
+ __free_raw_data(raw_data);
+ __free_raw_data(result);
+ }
+ }
+ }
+ }
+
+ if (!disconnected)
+ ERROR("client fd closed, worker_fd : %d", worker_fd);
+ INFO("task thread terminated --------------------------- (worker_fd : %d)", worker_fd);
+
+ pthread_mutex_lock(&ipc_svc->task_fds_mutex);
+ g_hash_table_remove(ipc_svc->task_fds, GINT_TO_POINTER(worker_fd)); // __worker_data_free will be called
+ pthread_mutex_unlock(&ipc_svc->task_fds_mutex);
+
+ close(worker_fd);
+ free ((void*)pollfds);
+
+ if (_client_disconnected_cb.callback)
+ _client_disconnected_cb.callback((pims_ipc_h)worker_id, _client_disconnected_cb.user_data);
+
+ return NULL;
}
-static void __launch_worker(void *(*start_routine) (void *), void *context)
+static void __launch_thread(void *(*start_routine) (void *), void *data)
{
- pthread_t worker;
- pthread_attr_t attr;
+ pthread_t worker;
+ pthread_attr_t attr;
- // set kernel thread
- pthread_attr_init(&attr);
- pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
+ // set kernel thread
+ pthread_attr_init(&attr);
+ pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
- pthread_create(&worker, &attr, start_routine, context);
- // detach this thread
- pthread_detach(worker);
+ pthread_create(&worker, &attr, start_routine, data);
+ // detach this thread
+ pthread_detach(worker);
}
static gboolean __is_worker_available()
{
- if (_g_singleton->workers)
- return TRUE;
- else
- return FALSE;
+ if (_g_singleton->workers)
+ return TRUE;
+ else
+ return FALSE;
}
-static int __get_worker(const char *pid, int *worker_id)
+static int __get_worker(const char *client_id, int *worker_id)
{
- ASSERT(pid);
- ASSERT(worker_id);
+ ASSERT(client_id);
+ ASSERT(worker_id);
- if (!__is_worker_available())
- {
- ERROR("There is no idle worker");
- return -1;
- }
- *worker_id = (int)(g_list_first(_g_singleton->workers)->data);
- _g_singleton->workers = g_list_delete_link(_g_singleton->workers,
- g_list_first(_g_singleton->workers));
+ if (!__is_worker_available()) {
+ ERROR("There is no idle worker");
+ return -1;
+ }
+ *worker_id = (int)(g_list_first(_g_singleton->workers)->data);
+ _g_singleton->workers = g_list_delete_link(_g_singleton->workers,
+ g_list_first(_g_singleton->workers));
- g_hash_table_insert(_g_singleton->client_table, g_strdup(pid), GINT_TO_POINTER(*worker_id));
+ g_hash_table_insert(_g_singleton->client_worker_map, g_strdup(client_id), GINT_TO_POINTER(*worker_id));
- return 0;
+ return 0;
}
-static int __find_worker(const char *pid, int *worker_id)
+static int __find_worker(const char *client_id, int *worker_fd)
{
- char *orig_pid = NULL;
-
- ASSERT(pid);
- ASSERT(worker_id);
-
- if (g_hash_table_lookup_extended(_g_singleton->client_table, pid,
- (gpointer*)&orig_pid, (gpointer*)worker_id) == TRUE)
- {
- VERBOSE("found worker id for %s = %x", pid, *worker_id);
- return 0;
- }
- else
- {
- VERBOSE("unable to find worker id for %s", pid);
- return -1;
- }
+ char *orig_pid = NULL;
+ int fd;
+
+ ASSERT(client_id);
+ ASSERT(worker_fd);
+
+ if (FALSE == g_hash_table_lookup_extended(_g_singleton->client_worker_map, client_id,
+ (gpointer*)&orig_pid, (gpointer*)&fd)) {
+ VERBOSE("unable to find worker id for %s", client_id);
+ return -1;
+ }
+
+ *worker_fd = GPOINTER_TO_INT(fd);
+ return 0;
}
-static void __remove_worker(const char *pid)
+static bool __request_pop(pims_ipc_request_s *data_queue, pims_ipc_raw_data_s **data)
{
- g_hash_table_remove(_g_singleton->client_table, pid);
+ bool ret = false;
+ GList *cursor;
+
+ pthread_mutex_lock(&data_queue->raw_data_mutex);
+ cursor = g_list_first(data_queue->raw_data);
+ if (cursor) {
+ *data = cursor->data;
+ data_queue->raw_data = g_list_delete_link(data_queue->raw_data, cursor);
+ (data_queue->request_count)--;
+
+ ret = true;
+ }
+ else
+ *data = NULL;
+
+ pthread_mutex_unlock(&data_queue->raw_data_mutex);
+ return ret;
}
-static void __terminate_worker(void *manager, int worker_id, const char *pid)
+static bool __worker_raw_data_push(pims_ipc_worker_data_s *worker_data, int client_fd, pims_ipc_raw_data_s *data)
{
- // send worker id
- zmq_msg_t worker_id_msg;
- zmq_msg_init_size(&worker_id_msg, PIMS_IPC_STRING_WORKER_ID_SIZE);
- char string_worker_id[PIMS_IPC_STRING_WORKER_ID_SIZE + 1] = "";
- memcpy(zmq_msg_data(&worker_id_msg), __get_string_worker_id(worker_id, string_worker_id),
- PIMS_IPC_STRING_WORKER_ID_SIZE);
- if (_pims_zmq_msg_send(&worker_id_msg, manager, ZMQ_SNDMORE) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- zmq_msg_close(&worker_id_msg);
- return;
- }
- zmq_msg_close(&worker_id_msg);
-
- // send pid
- zmq_msg_t pid_msg;
- zmq_msg_init_data(&pid_msg, (char*)pid, strlen(pid) + 1, NULL, NULL);
- if (_pims_zmq_msg_send(&pid_msg, manager, 0) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- zmq_msg_close(&pid_msg);
- return;
- }
- zmq_msg_close(&pid_msg);
+ pthread_mutex_lock(&worker_data->queue_mutex);
+ worker_data->queue = g_list_append(worker_data->queue, data);
+ worker_data->client_fd = client_fd;
+ pthread_mutex_unlock(&worker_data->queue_mutex);
+
+ return true;
}
-static gboolean __enqueue_zmq_msg(zmq_msg_t *zmsg)
+static int __process_router_event(pims_ipc_svc_s *ipc_svc, gboolean for_queue)
{
- zmq_msg_t *lpzmsg = NULL;
-
- if (zmsg)
- {
- lpzmsg = g_new0(zmq_msg_t, 1);
- zmq_msg_init(lpzmsg);
- zmq_msg_copy(lpzmsg, zmsg);
- }
- _g_singleton->requests = g_list_append(_g_singleton->requests, lpzmsg);
-
- return TRUE;
+ gboolean is_valid = FALSE;
+ pims_ipc_request_s *data_queue = NULL;
+ GList *queue_cursor = NULL;
+ int worker_fd = 0;
+ char *client_id = NULL;
+ int *org_fd;
+ int ret;
+
+ do {
+ pthread_mutex_lock(&ipc_svc->request_data_queue_mutex);
+ queue_cursor = g_list_first(ipc_svc->request_queue);
+ if (NULL == queue_cursor) {
+ pthread_mutex_unlock(&ipc_svc->request_data_queue_mutex);
+ return 0;
+ }
+ client_id = (char *)(queue_cursor->data);
+ ASSERT(client_id != NULL);
+ pthread_mutex_unlock(&ipc_svc->request_data_queue_mutex);
+
+ ret = g_hash_table_lookup_extended(ipc_svc->request_data_queue, (void*)client_id, (gpointer*)&org_fd, (gpointer*)&data_queue);
+
+ if (for_queue)
+ ipc_svc->delay_count--;
+
+ if (ret == TRUE && data_queue) {
+ int *org_fd;
+ pims_ipc_worker_data_s *worker_data = NULL;
+
+ pthread_mutex_lock(&data_queue->raw_data_mutex);
+ GList *cursor = g_list_first(data_queue->raw_data);
+ if (!cursor) {
+ pthread_mutex_unlock(&data_queue->raw_data_mutex);
+ break;
+ }
+
+ pims_ipc_raw_data_s *data = (pims_ipc_raw_data_s*)(cursor->data);
+ char *call_id = data->call_id;
+ int client_fd = data_queue->client_fd;
+
+ ASSERT(call_id != NULL);
+
+ VERBOSE("call_id = [%s]", call_id);
+ if (strcmp(PIMS_IPC_CALL_ID_CREATE, call_id) == 0) {
+ // Get a worker. If cannot get a worker, create a worker and enqueue a current request
+ __launch_thread(__worker_loop, ipc_svc);
+ if (__get_worker((const char*)client_id, &worker_fd) != 0) {
+ ipc_svc->delay_count++;
+ pthread_mutex_unlock(&data_queue->raw_data_mutex);
+ is_valid = TRUE;
+ break;
+ }
+ }
+ else {
+ // Find a worker
+ if (__find_worker((const char*)client_id, &worker_fd) != 0) {
+ ERROR("unable to find a worker");
+ pthread_mutex_unlock(&data_queue->raw_data_mutex);
+ break;
+ }
+ }
+ pthread_mutex_unlock(&data_queue->raw_data_mutex);
+
+ VERBOSE("routing client_id : %s, seq_no: %d, client_fd = %d, worker fd = %d", client_id, data->seq_no, client_fd, worker_fd);
+
+ if (worker_fd <= 0)
+ break;
+
+ pthread_mutex_lock(&ipc_svc->task_fds_mutex);
+ if (FALSE == g_hash_table_lookup_extended(ipc_svc->task_fds,
+ GINT_TO_POINTER(worker_fd), (gpointer*)&org_fd, (gpointer*)&worker_data)) {
+ ERROR("hash lookup fail : worker_fd (%d)", worker_fd);
+ pthread_mutex_unlock(&ipc_svc->task_fds_mutex);
+ break;
+ }
+
+ if (__request_pop(data_queue, &data)) {
+ __worker_raw_data_push(worker_data, client_fd, data);
+ write_command(worker_fd, 1);
+ }
+
+ pthread_mutex_unlock(&ipc_svc->task_fds_mutex);
+ }
+
+ pthread_mutex_lock(&ipc_svc->request_data_queue_mutex);
+ free(client_id);
+ ipc_svc->request_queue = g_list_delete_link(ipc_svc->request_queue, queue_cursor);
+ pthread_mutex_unlock(&ipc_svc->request_data_queue_mutex);
+
+ is_valid = TRUE;
+ } while (0);
+
+ if (is_valid == FALSE)
+ return -1;
+
+ return 1;
}
-static gboolean __dequeue_zmq_msg(zmq_msg_t *zmsg)
+static int __process_manager_event(pims_ipc_svc_s *ipc_svc)
{
- zmq_msg_t *lpzmsg = NULL;
-
- ASSERT(_g_singleton->requests);
- lpzmsg = (zmq_msg_t*)(g_list_first(_g_singleton->requests)->data);
- _g_singleton->requests = g_list_delete_link(_g_singleton->requests,
- g_list_first(_g_singleton->requests));
+ GList *cursor = NULL;
+ int worker_fd;
+
+ // client socket terminated without disconnect request
+ pthread_mutex_lock(&ipc_svc->manager_queue_from_epoll_mutex);
+ if (ipc_svc->manager_queue_from_epoll) {
+ cursor = g_list_first(ipc_svc->manager_queue_from_epoll);
+ char *client_id = (char*)cursor->data;
+ __find_worker(client_id, &worker_fd);
+
+ ipc_svc->manager_queue_from_epoll = g_list_delete_link(ipc_svc->manager_queue_from_epoll, cursor);
+ pthread_mutex_unlock(&ipc_svc->manager_queue_from_epoll_mutex);
+
+ // remove client_fd
+ g_hash_table_remove(ipc_svc->client_worker_map, client_id);
+ free(client_id);
+
+ // stop worker thread
+ if (worker_fd) {
+ int *org_fd;
+ pims_ipc_worker_data_s *worker_data;
+
+ pthread_mutex_lock(&ipc_svc->task_fds_mutex);
+ if (FALSE == g_hash_table_lookup_extended(ipc_svc->task_fds,
+ GINT_TO_POINTER(worker_fd), (gpointer*)&org_fd, (gpointer*)&worker_data)) {
+ ERROR("g_hash_table_lookup_extended fail : worker_fd (%d)", worker_fd);
+ pthread_mutex_unlock(&ipc_svc->task_fds_mutex);
+ return -1;
+ }
+ worker_data->stop_thread = true;
+ worker_data->client_fd = -1;
+ pthread_mutex_unlock(&ipc_svc->task_fds_mutex);
+
+ write_command(worker_fd, 1);
+ VERBOSE("write command to worker terminate (worker_fd : %d)", worker_fd);
+ }
+ return 0;
+ }
+ pthread_mutex_unlock(&ipc_svc->manager_queue_from_epoll_mutex);
+
+ // create new worker
+ pthread_mutex_lock(&ipc_svc->manager_queue_from_worker_mutex);
+ if (ipc_svc->manager_queue_from_worker) {
+
+ cursor = g_list_first(ipc_svc->manager_queue_from_worker);
+ while (cursor) {
+ worker_fd = (int)cursor->data;
+ ipc_svc->manager_queue_from_worker = g_list_delete_link(ipc_svc->manager_queue_from_worker, cursor);
+
+ if (worker_fd) {
+ DEBUG("add idle worker_fd : %d", worker_fd);
+ ipc_svc->workers = g_list_append(ipc_svc->workers, (void*)worker_fd);
+ }
+ cursor = g_list_first(ipc_svc->manager_queue_from_worker);
+ }
+ pthread_mutex_unlock(&ipc_svc->manager_queue_from_worker_mutex);
+ return 0;
+ }
+ pthread_mutex_unlock(&ipc_svc->manager_queue_from_worker_mutex);
+
+ return 0;
+}
- if (lpzmsg == NULL)
- return FALSE;
+// if delete = true, steal client_id, then free(client_id)
+// if delete = false, return client_id pointer, then do no call free(client_id
+static int __find_client_id(pims_ipc_svc_s *ipc_svc, int client_fd, bool delete, char **client_id)
+{
+ pims_ipc_client_map_s *client;
+ GList *cursor = NULL;
+ cursor = g_list_first(ipc_svc->client_id_fd_map);
+ while(cursor) {
+ client = cursor->data;
+ if (client->fd == client_fd) {
+ *client_id = client->id;
+ if (delete) {
+ client->id = NULL;
+ ipc_svc->client_id_fd_map = g_list_delete_link(ipc_svc->client_id_fd_map, cursor); //free(client);
+ free(client);
+ }
+ return 0;
+ }
+ cursor = g_list_next(cursor);
+ }
+ return -1;
+}
- zmq_msg_copy(zmsg, lpzmsg);
- zmq_msg_close(lpzmsg);
- g_free(lpzmsg);
+static void __request_push(pims_ipc_svc_s *ipc_svc, char *client_id, int client_fd, pims_ipc_raw_data_s *data)
+{
+ int ret;
+ int *org_fd;
+ pims_ipc_request_s *data_queue = NULL;
+
+ pthread_mutex_lock(&ipc_svc->request_data_queue_mutex);
+ ret = g_hash_table_lookup_extended(ipc_svc->request_data_queue, (void*)client_id, (gpointer*)&org_fd,(gpointer*)&data_queue);
+ if (ret == TRUE && data_queue) {
+ }
+ else {
+ data_queue = calloc(1, sizeof(pims_ipc_request_s));
+ data_queue->request_count = 0;
+ pthread_mutex_init(&data_queue->raw_data_mutex, 0);
+
+ g_hash_table_insert(ipc_svc->request_data_queue, g_strdup(client_id), data_queue);
+ }
+ ipc_svc->request_queue = g_list_append(ipc_svc->request_queue, g_strdup(client_id));
+ pthread_mutex_unlock(&ipc_svc->request_data_queue_mutex);
+
+ pthread_mutex_lock(&data_queue->raw_data_mutex);
+ data_queue->raw_data = g_list_append(data_queue->raw_data, data);
+ data_queue->client_fd = client_fd;
+ data_queue->request_count++;
+ pthread_mutex_unlock(&data_queue->raw_data_mutex);
+}
- return TRUE;
+static void __delete_request_queue(pims_ipc_svc_s *ipc_svc, char *client_id)
+{
+ pims_ipc_request_s *data_queue = NULL;
+ int ret;
+ int *org_fd;
+ GList *l;
+ GList *cursor;
+
+ pthread_mutex_lock(&ipc_svc->request_data_queue_mutex);
+ ret = g_hash_table_lookup_extended(ipc_svc->request_data_queue, (void*)client_id, (gpointer*)&org_fd,(gpointer*)&data_queue);
+ if (ret == TRUE)
+ g_hash_table_remove(ipc_svc->request_data_queue, (void*)client_id);
+
+ cursor = g_list_first(ipc_svc->request_queue);
+ while (cursor) {
+ l = cursor;
+ char *id = l->data;
+ cursor = g_list_next(cursor);
+ if (id && strcmp(id, client_id) == 0) {
+ free(id);
+ ipc_svc->request_queue = g_list_delete_link(ipc_svc->request_queue, l);
+ }
+ }
+ pthread_mutex_unlock(&ipc_svc->request_data_queue_mutex);
+
+ if (data_queue) {
+ pthread_mutex_lock(&data_queue->raw_data_mutex);
+ cursor = g_list_first(data_queue->raw_data);
+ pims_ipc_raw_data_s *data;
+ while(cursor) {
+ l = cursor;
+ data = (pims_ipc_raw_data_s *)cursor->data;
+ cursor = g_list_next(cursor);
+ data_queue->raw_data = g_list_delete_link(data_queue->raw_data, l);
+ __free_raw_data(data);
+ }
+ g_list_free(data_queue->raw_data);
+ pthread_mutex_unlock(&data_queue->raw_data_mutex);
+ pthread_mutex_destroy(&data_queue->raw_data_mutex);
+ free(data_queue);
+ }
}
-static int __process_router_event(void *context, void *router, void *worker, gboolean for_queue)
+static int __send_identify(int fd, unsigned int seq_no, char *id, int id_len)
{
- char *pid = NULL;
- char *call_id = NULL;
- int64_t more = 0;
- size_t more_size = sizeof(more);
- int worker_id = -1;
- gboolean is_with_data = FALSE;
- gboolean is_valid = FALSE;
-
-#ifdef _TEST
- struct timeval tv;
- gettimeofday(&tv, NULL);
- printf("router time[%lu:%lu]\n", tv.tv_sec, tv.tv_usec);
-#endif
-
- // init messages for receiving
- zmq_msg_t pid_msg;
- zmq_msg_t sequence_no_msg;
- zmq_msg_t call_id_msg;
- zmq_msg_t data_msg;
-
- zmq_msg_init(&pid_msg);
- zmq_msg_init(&sequence_no_msg);
- zmq_msg_init(&call_id_msg);
- zmq_msg_init(&data_msg);
-
- // relay a request from a client to a worker
- do {
- if (for_queue)
- {
- // dequeue a request
- __dequeue_zmq_msg(&pid_msg);
- __dequeue_zmq_msg(&sequence_no_msg);
- __dequeue_zmq_msg(&call_id_msg);
- is_with_data = __dequeue_zmq_msg(&data_msg);
-
- if (is_with_data)
- __dequeue_zmq_msg(NULL);
- }
- else
- {
- // read pid
- if (_pims_zmq_msg_recv(&pid_msg, router, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- break;
- }
-
- // read empty and kill
- zmq_msg_t empty_msg;
- zmq_msg_init(&empty_msg);
- if (_pims_zmq_msg_recv(&empty_msg, router, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- zmq_msg_close(&empty_msg);
- break;
- }
- zmq_msg_close(&empty_msg);
-
- // read sequence no
- more = 0;
- zmq_getsockopt(router, ZMQ_RCVMORE, &more, &more_size);
- if (!more)
- {
- ERROR("recv error : corrupted message");
- break;
- }
- if (_pims_zmq_msg_recv(&sequence_no_msg, router, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- break;
- }
-
- // read call id
- more = 0;
- zmq_getsockopt(router, ZMQ_RCVMORE, &more, &more_size);
- if (!more)
- {
- ERROR("recv error : corrupted message");
- break;
- }
- if (_pims_zmq_msg_recv(&call_id_msg, router, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- break;
- }
-
- // read data
- more = 0;
- zmq_getsockopt(router, ZMQ_RCVMORE, &more, &more_size);
- if (more)
- {
- is_with_data = TRUE;
- if (_pims_zmq_msg_recv(&data_msg, router, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- break;
- }
- }
- }
-
- pid = zmq_msg_data(&pid_msg);
- ASSERT(pid != NULL);
- VERBOSE("client pid = %s", pid);
-
- call_id = (char*)zmq_msg_data(&call_id_msg);
- ASSERT(call_id != NULL);
- VERBOSE("call_id = [%s], create_call_id = [%s]", PIMS_IPC_CALL_ID_CREATE, call_id);
- if (strcmp(PIMS_IPC_CALL_ID_CREATE, call_id) == 0)
- {
- // Get a worker. If cannot get a worker, create a worker and enqueue a current request
- __launch_worker(__worker_loop, context);
- if (__get_worker((const char*)pid, &worker_id) != 0)
- {
- // enqueue a request until a new worker will be registered
- __enqueue_zmq_msg(&pid_msg);
- __enqueue_zmq_msg(&sequence_no_msg);
- __enqueue_zmq_msg(&call_id_msg);
- if (is_with_data)
- __enqueue_zmq_msg(&data_msg);
- __enqueue_zmq_msg(NULL);
-
- is_valid = TRUE;
- break;
- }
- }
- else
- {
- // Find a worker
- if (__find_worker((const char*)pid, &worker_id) != 0)
- {
- ERROR("unable to find a worker");
- break;
- }
-
- if (strcmp(PIMS_IPC_CALL_ID_DESTROY, call_id) == 0)
- {
- __remove_worker((const char*)pid);
- }
- }
-
- VERBOSE("routing worker id = %x", worker_id);
- // send worker id
- zmq_msg_t worker_id_msg;
- zmq_msg_init_size(&worker_id_msg, PIMS_IPC_STRING_WORKER_ID_SIZE);
- char string_worker_id[PIMS_IPC_STRING_WORKER_ID_SIZE + 1] = "";
- memcpy(zmq_msg_data(&worker_id_msg), __get_string_worker_id(worker_id, string_worker_id),
- PIMS_IPC_STRING_WORKER_ID_SIZE);
- if (_pims_zmq_msg_send(&worker_id_msg, worker, ZMQ_SNDMORE) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- zmq_msg_close(&worker_id_msg);
- break;
- }
- zmq_msg_close(&worker_id_msg);
-
- // send pid
- if (_pims_zmq_msg_send(&pid_msg, worker, ZMQ_SNDMORE) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- break;
- }
-
- // send sequence no
- if (_pims_zmq_msg_send(&sequence_no_msg, worker, ZMQ_SNDMORE) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- break;
- }
-
- // send call id
- if (_pims_zmq_msg_send(&call_id_msg, worker, is_with_data?ZMQ_SNDMORE:0) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- break;
- }
-
- // send data
- if (is_with_data)
- {
- if (_pims_zmq_msg_send(&data_msg, worker, 0) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- break;
- }
- }
-
- is_valid = TRUE;
- } while (0);
-
- zmq_msg_close(&pid_msg);
- zmq_msg_close(&sequence_no_msg);
- zmq_msg_close(&call_id_msg);
- zmq_msg_close(&data_msg);
-
-#ifdef _TEST
- gettimeofday(&tv, NULL);
- printf("router time[%lu:%lu]\n", tv.tv_sec, tv.tv_usec);
-#endif
-
- if (is_valid == FALSE)
- return -1;
-
- return 0;
+ int len = sizeof(unsigned int) // total size
+ + id_len + sizeof(unsigned int) // id
+ + sizeof(unsigned int); // seq_no
+
+ char buf[len+1];
+
+ int length = 0;
+ memset(buf, 0x0, len+1);
+
+ // total len
+ memcpy(buf, (void*)&len, sizeof(unsigned int));
+ length += sizeof(unsigned int);
+
+ // id
+ memcpy(buf+length, (void*)&(id_len), sizeof(unsigned int));
+ length += sizeof(unsigned int);
+ memcpy(buf+length, (void*)(id), id_len);
+ length += id_len;
+
+ // seq_no
+ memcpy(buf+length, (void*)&(seq_no), sizeof(unsigned int));
+ length += sizeof(unsigned int);
+
+ return socket_send(fd, buf, length);
}
-static int __process_worker_event(void *context, void *worker, void *router)
+static int __recv_raw_data(int fd, pims_ipc_raw_data_s **data, bool *identity)
{
- zmq_msg_t message;
- int64_t more = 0;
- size_t more_size = sizeof(more);
-
- // Remove worker_id
- zmq_msg_init(&message);
- if (_pims_zmq_msg_recv(&message, worker, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- }
- zmq_msg_close(&message);
-
- while (1)
- {
- // Process all parts of the message
- zmq_msg_init(&message);
- if (_pims_zmq_msg_recv(&message, worker, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- }
- more = 0;
- zmq_getsockopt(worker, ZMQ_RCVMORE, &more, &more_size);
- VERBOSE("router received a message : more[%u]", (unsigned int)more);
- if (_pims_zmq_msg_send(&message, router, more?ZMQ_SNDMORE:0) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- }
- zmq_msg_close(&message);
- if (!more)
- break; // Last message part
- }
-
- return 0;
+ int len = 0;
+ pims_ipc_raw_data_s *temp;
+
+ /* read the size of message. note that ioctl is non-blocking */
+ if (ioctl(fd, FIONREAD, &len)) {
+ ERROR("ioctl failed: %d", errno);
+ return -1;
+ }
+
+ /* when server or client closed socket */
+ if (len == 0) {
+ INFO("[IPC Socket] connection is closed");
+ return 0;
+ }
+
+ temp = (pims_ipc_raw_data_s*)calloc(1, sizeof(pims_ipc_raw_data_s));
+ temp->client_id = NULL;
+ temp->client_id_len = 0;
+ temp->call_id = NULL;
+ temp->call_id_len = 0;
+ temp->seq_no = 0;
+ temp->is_data = FALSE;
+ temp->data = NULL;
+ temp->data_len = 0;
+
+ int ret = 0;
+ unsigned int read_len = 0;
+ unsigned int total_len = 0;
+ unsigned int is_data = FALSE;
+
+ do {
+ // total length
+ ret = read(fd, (void *)&total_len, sizeof(unsigned int));
+ if (ret < 0) { ERROR("read error"); break; }
+ read_len += ret;
+
+ // client_id
+ ret = read(fd, (void *)&(temp->client_id_len), sizeof(unsigned int));
+ if (ret < 0) { ERROR("read error"); break; }
+ read_len += ret;
+
+ temp->client_id = calloc(1, temp->client_id_len+1);
+ ret = socket_recv(fd, (void *)&(temp->client_id), temp->client_id_len);
+ if (ret < 0) { ERROR("socket_recv error"); break; }
+ read_len += ret;
+
+ // sequnce no
+ ret = read(fd, (void *)&(temp->seq_no), sizeof(unsigned int));
+ if (ret < 0) { ERROR("read error"); break; }
+ read_len += ret;
+
+ if (total_len == read_len) {
+ *data = temp;
+ *identity = true;
+ return read_len;
+ }
+
+ // call_id
+ ret = read(fd, (void *)&(temp->call_id_len), sizeof(unsigned int));
+ if (ret < 0) { ERROR("read error"); break; }
+ read_len += ret;
+
+ temp->call_id = calloc(1, temp->call_id_len+1);
+ ret = socket_recv(fd, (void *)&(temp->call_id), temp->call_id_len);
+ if (ret < 0) { ERROR("socket_recv error"); break; }
+ read_len += ret;
+
+ // is_data
+ ret = read(fd, (void *)&(is_data), sizeof(unsigned int));
+ if (ret < 0) { ERROR("read error"); break; }
+ read_len += ret;
+
+ // data
+ if (is_data) {
+ temp->is_data = TRUE;
+ ret = read(fd, (void *)&(temp->data_len), sizeof(unsigned int));
+ if (ret < 0) { ERROR("read error"); break; }
+ read_len += ret;
+
+ temp->data = calloc(1, temp->data_len+1);
+ ret = socket_recv(fd, (void *)&(temp->data), temp->data_len);
+ if (ret < 0) { ERROR("socket_recv error"); break; }
+ read_len += ret;
+ }
+
+ INFO("client_id : %s, call_id : %s, seq_no : %d", temp->client_id, temp->call_id, temp->seq_no);
+
+ *data = temp;
+ *identity = false;
+ }while(0);
+
+ if (ret < 0) {
+ __free_raw_data(temp);
+ *data = NULL;
+ *identity = false;
+ }
+
+ return read_len;
}
-static int __process_manager_event(void *context, void *manager)
+static gboolean __request_handler(GIOChannel *src, GIOCondition condition, gpointer data)
{
- zmq_msg_t worker_id_msg;
- int worker_id = -1;
-
- zmq_msg_init(&worker_id_msg);
- if (_pims_zmq_msg_recv(&worker_id_msg, manager, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- zmq_msg_close(&worker_id_msg);
- return -1;
- }
- zmq_msg_close(&worker_id_msg);
-
- zmq_msg_init(&worker_id_msg);
- if (_pims_zmq_msg_recv(&worker_id_msg, manager, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- zmq_msg_close(&worker_id_msg);
- return -1;
- }
- memcpy(&worker_id, zmq_msg_data(&worker_id_msg), sizeof(int));
- zmq_msg_close(&worker_id_msg);
-
- VERBOSE("registered worker id = %x", worker_id);
- _g_singleton->workers = g_list_append(_g_singleton->workers, GINT_TO_POINTER(worker_id));
-
- return 0;
+ int ret;
+ int event_fd = g_io_channel_unix_get_fd(src);
+ char *client_id = NULL;
+ pims_ipc_svc_s *ipc_svc = (pims_ipc_svc_s*)data;
+
+ if (G_IO_HUP & condition) {
+ INFO("client closed ------------------------client_fd : %d", event_fd);
+
+ close(event_fd);
+
+ // Find client_id
+ __find_client_id(ipc_svc, event_fd, true, &client_id);
+
+ // Send client_id to manager to terminate worker thread
+ if (client_id) {
+ pthread_mutex_lock(&ipc_svc->manager_queue_from_epoll_mutex);
+ ipc_svc->manager_queue_from_epoll = g_list_append(ipc_svc->manager_queue_from_epoll, (void*)g_strdup(client_id));
+ pthread_mutex_unlock(&ipc_svc->manager_queue_from_epoll_mutex);
+ write_command(ipc_svc->manager, 1);
+
+ __delete_request_queue(ipc_svc, client_id);
+ free(client_id);
+ }
+
+ return FALSE;
+ }
+
+ // receive data from client
+ int recv_len;
+ bool identity = false;
+ pims_ipc_raw_data_s *req = NULL;
+
+ recv_len = __recv_raw_data(event_fd, &req, &identity);
+ if (recv_len > 0) {
+ // send command to router
+ if (identity) {
+ pims_ipc_client_map_s *client = (pims_ipc_client_map_s*)calloc(1, sizeof(pims_ipc_client_map_s));
+ client->fd = event_fd;
+ client->id = req->client_id;
+ req->client_id = NULL;
+ ipc_svc->client_id_fd_map = g_list_append(ipc_svc->client_id_fd_map, client);
+
+ // send server pid to client
+ char temp[100];
+ snprintf(temp, sizeof(temp), "%x", getpid());
+ ret = __send_identify(event_fd, req->seq_no, temp, strlen(temp));
+
+ __free_raw_data(req);
+ if (ret < 0)
+ return FALSE;
+ return TRUE;
+ }
+
+ __find_client_id(ipc_svc, event_fd, false, &client_id);
+
+ if (client_id) {
+ __request_push(ipc_svc, client_id, event_fd, req);
+ write_command(ipc_svc->router, 1);
+ }
+ else
+ ERROR("__find_client_id fail : event_fd (%d)", event_fd);
+ }
+ else {
+ ERROR("receive invalid : %d", event_fd);
+ close(event_fd);
+ return FALSE;
+ }
+
+ return TRUE;
}
-static int __process_monitor_event(void *context, void *monitor, void *manager)
+static gboolean __socket_handler(GIOChannel *src, GIOCondition condition, gpointer data)
{
- int worker_id = -1;
- char *pid = NULL;
- zmq_msg_t pid_msg;
-
- VERBOSE("");
-
- // read pid
- zmq_msg_init(&pid_msg);
- if (_pims_zmq_msg_recv(&pid_msg, monitor, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- zmq_msg_close(&pid_msg);
- return -1;
- }
-
- pid = (char*)zmq_msg_data(&pid_msg);
- ASSERT(pid);
- VERBOSE("client pid = %s", pid);
-
- if (__find_worker(pid, &worker_id) != 0)
- return 0;
-
- VERBOSE("found worker id for %s = %x", pid, worker_id);
-
- __terminate_worker(manager, worker_id, pid);
- __remove_worker(pid);
-
- zmq_msg_close(&pid_msg);
-
- return 0;
+ GIOChannel *channel;
+ pims_ipc_svc_s *ipc_svc = (pims_ipc_svc_s*)data;
+ int client_sockfd = -1;
+ int sockfd = ipc_svc->sockfd;
+ struct sockaddr_un clientaddr;
+ socklen_t client_len = sizeof(clientaddr);
+
+ client_sockfd = accept(sockfd, (struct sockaddr *)&clientaddr, &client_len);
+ if (-1 == client_sockfd) {
+ ERROR("accept error : %s", strerror(errno));
+ return TRUE;
+ }
+
+ channel = g_io_channel_unix_new(client_sockfd);
+ g_io_add_watch(channel, G_IO_IN|G_IO_HUP, __request_handler, data);
+ g_io_channel_unref(channel);
+
+ return TRUE;
}
-static void __client_closed_cb(const char *pid, void *data)
+static void* __main_loop(void *user_data)
{
- pims_ipc_svc_t *ipc_svc = (pims_ipc_svc_t*)data;
-
- VERBOSE("client pid = %s", pid);
-
- zmq_msg_t pid_msg;
- zmq_msg_init_size(&pid_msg, strlen(pid) + 1);
- memcpy(zmq_msg_data(&pid_msg), pid, strlen(pid) + 1);
- if (_pims_zmq_msg_send(&pid_msg, ipc_svc->monitor, 0) == -1)
- ERROR("send error : %s", zmq_strerror(errno));
- zmq_msg_close(&pid_msg);
+ int ret;
+ struct sockaddr_un addr;
+ GIOChannel *gio = NULL;
+ pims_ipc_svc_s *ipc_svc = (pims_ipc_svc_s*)user_data;
+
+ if (sd_listen_fds(1) == 1 && sd_is_socket_unix(SD_LISTEN_FDS_START, SOCK_STREAM, -1, ipc_svc->service, 0) > 0) {
+ ipc_svc->sockfd = SD_LISTEN_FDS_START;
+ }
+ else {
+ unlink(ipc_svc->service);
+ ipc_svc->sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
+
+ bzero(&addr, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", ipc_svc->service);
+
+ ret = bind(ipc_svc->sockfd, (struct sockaddr *)&addr, sizeof(addr));
+ if (ret != 0)
+ ERROR("bind error :%d", ret);
+ ret = listen(ipc_svc->sockfd, 30);
+
+ ret = chown(ipc_svc->service, getuid(), ipc_svc->group);
+ ret = chmod(ipc_svc->service, ipc_svc->mode);
+ }
+
+ gio = g_io_channel_unix_new(ipc_svc->sockfd);
+
+ g_io_add_watch(gio, G_IO_IN, __socket_handler, (gpointer)ipc_svc);
+
+ return NULL;
}
-static int __open_zmq_socket(void *context, pims_ipc_svc_t *ipc_svc)
+static int __open_router_fd(pims_ipc_svc_s *ipc_svc)
{
- char *path = NULL;
- int ret = -1;
- int i = 0;
-
- void *router = zmq_socket(context, ZMQ_ROUTER);
- if (!router)
- {
- ERROR("socket error : %s", zmq_strerror(errno));
- return -1;
- }
- path = g_strdup_printf("ipc://%s", ipc_svc->service);
- if (zmq_bind(router, path) != 0)
- {
- ERROR("bind error : %s", zmq_strerror(errno));
- zmq_close(router);
- return -1;
- }
- g_free(path);
-
- ret = chown(ipc_svc->service, getuid(), ipc_svc->group);
- ret = chmod(ipc_svc->service, ipc_svc->mode);
-
- void *worker = zmq_socket(context, ZMQ_ROUTER);
- if (!worker)
- {
- ERROR("socket error : %s", zmq_strerror(errno));
- zmq_close(router);
- return -1;
- }
- path = g_strdup_printf("inproc://%s-%s", ipc_svc->service, PIMS_IPC_DEALER_PATH);
- if (zmq_bind(worker, path) != 0)
- {
- ERROR("bind error : %s", zmq_strerror(errno));
- zmq_close(router);
- zmq_close(worker);
- return -1;
- }
- g_free(path);
-
- void *manager = zmq_socket(context, ZMQ_ROUTER);
- if (!manager)
- {
- ERROR("socket error : %s", zmq_strerror(errno));
- zmq_close(router);
- zmq_close(worker);
- return -1;
- }
- path = g_strdup_printf("inproc://%s-%s", ipc_svc->service, PIMS_IPC_MANAGER_PATH);
- if (zmq_bind(manager, path) != 0)
- {
- ERROR("bind error : %s", zmq_strerror(errno));
- zmq_close(router);
- zmq_close(worker);
- zmq_close(manager);
- return -1;
- }
- g_free(path);
-
- void *monitor = zmq_socket(context, ZMQ_PAIR);
- if (!monitor)
- {
- ERROR("socket error : %s", zmq_strerror(errno));
- zmq_close(router);
- zmq_close(worker);
- zmq_close(manager);
- return -1;
- }
- path = g_strdup_printf("inproc://%s-%s", ipc_svc->service, PIMS_IPC_MONITOR2_PATH);
- if (zmq_bind(monitor, path) != 0)
- {
- ERROR("bind error : %s", zmq_strerror(errno));
- zmq_close(router);
- zmq_close(worker);
- zmq_close(manager);
- zmq_close(monitor);
- return -1;
- }
- g_free(path);
-
- ipc_svc->context = context;
- ipc_svc->router = router;
- ipc_svc->worker = worker;
- ipc_svc->manager = manager;
- ipc_svc->monitor = monitor;
-
- path = g_strdup_printf("%s-%s", ipc_svc->service, PIMS_IPC_MONITOR_PATH);
- ret = _server_socket_init(path, ipc_svc->group, ipc_svc->mode, __client_closed_cb, ipc_svc);
- ASSERT(ret != -1);
- g_free(path);
-
- // launch worker threads in advance
- for (i = 0; i < ipc_svc->workers_max_count; i++)
- __launch_worker(__worker_loop, context);
-
- return 0;
+ int ret = -1;
+ int flags;
+ int router;
+ int manager;
+
+ // router inproc eventfd
+ router = eventfd(0,0);
+ if (-1 == router) {
+ ERROR("eventfd error : %d", errno);
+ return -1;
+ }
+ VERBOSE("router :%d\n", router);
+
+ flags = fcntl(router, F_GETFL, 0);
+ if (flags == -1)
+ flags = 0;
+ ret = fcntl (router, F_SETFL, flags | O_NONBLOCK);
+ VERBOSE("rounter fcntl : %d\n", ret);
+
+ // manager inproc eventfd
+ manager = eventfd(0,0);
+ if (-1 == manager) {
+ ERROR("eventfd error : %d", errno);
+ close(router);
+ return -1;
+ }
+ VERBOSE("manager :%d\n", manager);
+
+ flags = fcntl(manager, F_GETFL, 0);
+ if (flags == -1)
+ flags = 0;
+ ret = fcntl (manager, F_SETFL, flags | O_NONBLOCK);
+ VERBOSE("manager fcntl : %d\n", ret);
+
+ ipc_svc->router = router;
+ ipc_svc->manager = manager;
+
+ return 0;
}
-static void __close_zmq_socket(pims_ipc_svc_t *ipc_svc)
+static void __close_router_fd(pims_ipc_svc_s *ipc_svc)
{
- zmq_close(ipc_svc->router);
- zmq_close(ipc_svc->worker);
- zmq_close(ipc_svc->manager);
- zmq_close(ipc_svc->monitor);
+ close(ipc_svc->router);
+ close(ipc_svc->manager);
}
-static int __open_zmq_socket_for_publish(void *context, pims_ipc_svc_for_publish_t *ipc_svc)
+static void* __publish_loop(void *user_data)
{
- char *path = NULL;
- int ret = -1;
-
- ipc_svc->context = context;
- void *publisher = NULL;
- publisher = zmq_socket(context, ZMQ_PUB);
- if (!publisher)
- {
- ERROR("socket error : %s", zmq_strerror(errno));
- return -1;
- }
-
- path = g_strdup_printf("ipc://%s", ipc_svc->service);
- if (zmq_bind(publisher, path) != 0)
- {
- ERROR("bind error : %s", zmq_strerror(errno));
- zmq_close(publisher);
- return -1;
- }
- g_free(path);
-
- ret = chown(ipc_svc->service, getuid(), ipc_svc->group);
- ret = chmod(ipc_svc->service, ipc_svc->mode);
-
- ipc_svc->context = context;
- ipc_svc->publisher = publisher;
-
- return 0;
+ int ret;
+ int epfd;
+
+ struct sockaddr_un addr;
+ struct epoll_event ev = {0};
+ pims_ipc_svc_for_publish_s *ipc_svc = (pims_ipc_svc_for_publish_s*)user_data;
+
+ unlink(ipc_svc->service);
+ ipc_svc->publish_sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
+
+ bzero(&addr, sizeof(struct sockaddr_un));
+ addr.sun_family = AF_UNIX;
+ snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", ipc_svc->service);
+
+ int flags = fcntl (ipc_svc->publish_sockfd, F_GETFL, 0);
+ if (flags == -1)
+ flags = 0;
+ ret = fcntl (ipc_svc->publish_sockfd, F_SETFL, flags | O_NONBLOCK);
+ VERBOSE("publish socketfd fcntl : %d\n", ret);
+
+ ret = bind(ipc_svc->publish_sockfd, (struct sockaddr *)&(addr), sizeof(struct sockaddr_un));
+ if (ret != 0)
+ ERROR("bind error :%d", ret);
+ ret = listen(ipc_svc->publish_sockfd, 30);
+ WARN_IF(ret != 0, "listen error :%d", ret);
+
+ ret = chown(ipc_svc->service, getuid(), ipc_svc->group);
+ WARN_IF(ret != 0, "listen error :%d", ret);
+ ret = chmod(ipc_svc->service, ipc_svc->mode);
+ WARN_IF(ret != 0, "listen error :%d", ret);
+
+ epfd = epoll_create(MAX_EPOLL_EVENT);
+
+ ev.events = EPOLLIN | EPOLLHUP;
+ ev.data.fd = ipc_svc->publish_sockfd;
+
+ ret = epoll_ctl(epfd, EPOLL_CTL_ADD, ipc_svc->publish_sockfd, &ev);
+ WARN_IF(ret != 0, "listen error :%d", ret);
+
+ while (!ipc_svc->epoll_stop_thread) {
+ int i = 0;
+ struct epoll_event events[MAX_EPOLL_EVENT] = {{0}, };
+ int event_num = epoll_wait(epfd, events, MAX_EPOLL_EVENT, -1);
+
+ if (ipc_svc->epoll_stop_thread)
+ break;
+
+ if (event_num == -1) {
+ if (errno != EINTR) {
+ ERROR("errno:%d\n", errno);
+ break;
+ }
+ }
+
+ for (i = 0; i < event_num; i++) {
+ int event_fd = events[i].data.fd;
+
+ if (events[i].events & EPOLLHUP) {
+ VERBOSE("client closed -----------------------------------------:%d", event_fd);
+ if (epoll_ctl(epfd, EPOLL_CTL_DEL, event_fd, events) == -1) {
+ ERROR("epoll_ctl (EPOLL_CTL_DEL) fail : errno(%d)", errno);
+ }
+ close(event_fd);
+
+ // Find client_id and delete
+ GList *cursor = NULL;
+
+ pthread_mutex_lock(&ipc_svc->subscribe_fds_mutex);
+ cursor = g_list_first(ipc_svc->subscribe_fds);
+ while (cursor) {
+ if (event_fd == (int)cursor->data) {
+ ipc_svc->subscribe_fds = g_list_delete_link(ipc_svc->subscribe_fds, cursor);
+ break;
+ }
+ cursor = g_list_next(cursor);
+ }
+ pthread_mutex_unlock(&ipc_svc->subscribe_fds_mutex);
+ continue;
+ }
+ else if (event_fd == ipc_svc->publish_sockfd) { // connect client
+ struct sockaddr_un remote;
+ int remote_len = sizeof(remote);
+ int client_fd = accept(ipc_svc->publish_sockfd, (struct sockaddr *)&remote, (socklen_t*) &remote_len);
+ if (client_fd == -1) {
+ ERROR("accept fail : errno : %d", errno);
+ continue;
+ }
+ VERBOSE("client subscriber connect: %d", client_fd);
+
+ pthread_mutex_lock(&ipc_svc->subscribe_fds_mutex);
+ ipc_svc->subscribe_fds = g_list_append(ipc_svc->subscribe_fds, (void*)client_fd);
+ pthread_mutex_unlock(&ipc_svc->subscribe_fds_mutex);
+
+ ev.events = EPOLLIN;
+ ev.data.fd = client_fd;
+ if (epoll_ctl(epfd, EPOLL_CTL_ADD, client_fd, &ev) == -1) {
+ ERROR("epoll_ctl (EPOLL_CTL_ADD) fail : error(%d)\n", errno);
+ continue;
+ }
+ }
+ }
+ }
+
+ close(ipc_svc->publish_sockfd);
+ close(epfd);
+
+ return NULL;
}
-static void __close_zmq_socket_for_publish(pims_ipc_svc_for_publish_t *ipc_svc)
+static void __stop_for_publish(pims_ipc_svc_for_publish_s *ipc_svc)
{
- zmq_close(ipc_svc->publisher);
+ ipc_svc->epoll_stop_thread = true;
}
-static void* __main_loop(void *args)
+static void* __router_loop(void *data)
{
- char *path = NULL;
- int ret = -1;
- pims_ipc_svc_t *ipc_svc = (pims_ipc_svc_t*)args;
-
- void *monitor_peer = zmq_socket(ipc_svc->context, ZMQ_PAIR);
- ASSERT(monitor_peer);
-
- path = g_strdup_printf("inproc://%s-%s", ipc_svc->service, PIMS_IPC_MONITOR2_PATH);
- ret = zmq_connect(monitor_peer, path);
- ASSERT(ret == 0);
- g_free(path);
-
- // poll all sockets
- while (1)
- {
- zmq_pollitem_t items[] = {
- {ipc_svc->router, 0, ZMQ_POLLIN, 0},
- {ipc_svc->worker, 0, ZMQ_POLLIN, 0},
- {ipc_svc->manager, 0, ZMQ_POLLIN, 0},
- {monitor_peer, 0, ZMQ_POLLIN, 0}
- };
-
- if (zmq_poll(items, 4, -1) == -1)
- {
- if (errno == EINTR)
- continue;
-
- ERROR("poll error : %s", zmq_strerror(errno));
- break;
- }
-
- if (items[0].revents & ZMQ_POLLIN)
- {
- __process_router_event(ipc_svc->context, ipc_svc->router, ipc_svc->worker, FALSE);
- }
-
- if (items[1].revents & ZMQ_POLLIN)
- {
- __process_worker_event(ipc_svc->context, ipc_svc->worker, ipc_svc->router);
- }
-
- if (items[2].revents & ZMQ_POLLIN)
- {
- __process_manager_event(ipc_svc->context, ipc_svc->manager);
- if (ipc_svc->requests)
- __process_router_event(ipc_svc->context, ipc_svc->router, ipc_svc->worker, TRUE);
- }
-
- if (items[3].revents & ZMQ_POLLIN)
- {
- __process_monitor_event(ipc_svc->context, monitor_peer, ipc_svc->manager);
- }
- }
-
- zmq_close(monitor_peer);
-
- return NULL;
+ pims_ipc_svc_s *ipc_svc = (pims_ipc_svc_s*)data;
+ int fd_count = 2;
+ struct pollfd *pollfds;
+
+ pollfds = (struct pollfd*) malloc (fd_count * sizeof (struct pollfd));
+
+ pollfds[0].fd = ipc_svc->router;
+ pollfds[0].events = POLLIN;
+ pollfds[1].fd = ipc_svc->manager;
+ pollfds[1].events = POLLIN;
+
+ while (1) {
+ int ret = -1;
+ uint64_t dummy;
+ int check_router_queue = -1;
+ int check_manager_queue = -1;
+
+ while (1) {
+ ret = poll(pollfds, fd_count, 1000);
+ if (ret == -1 && errno == EINTR) {
+ //free (pollfds);
+ continue; //return NULL;
+ }
+ break;
+ }
+
+ if (ret > 0) {
+ if (pollfds[0].revents & POLLIN) {
+ // request router: send request to worker
+ if (sizeof (dummy) == read_command(pollfds[0].fd, &dummy)) {
+ check_router_queue = __process_router_event(ipc_svc, false);
+ }
+ }
+
+ if (pollfds[1].revents & POLLIN) {
+ // worker manager
+ if (sizeof (dummy) == read_command(pollfds[1].fd, &dummy)) {
+ check_manager_queue = __process_manager_event(ipc_svc);
+ if (ipc_svc->delay_count > 0)
+ check_router_queue = __process_router_event(ipc_svc, true);
+ }
+ }
+ }
+
+ // check queue
+ while(check_router_queue > 0 || check_manager_queue > 0) {
+ read_command(pollfds[0].fd, &dummy);
+ check_router_queue = __process_router_event(ipc_svc, false);
+
+ read_command(pollfds[1].fd, &dummy);
+ check_manager_queue = __process_manager_event(ipc_svc);
+ if (ipc_svc->delay_count > 0)
+ check_router_queue = __process_router_event(ipc_svc, true);
+ }
+ }
+
+ free(pollfds);
+
+ return NULL;
}
API void pims_ipc_svc_run_main_loop(GMainLoop* loop)
{
- int retval = -1;
- GMainLoop* main_loop = loop;
+ int ret = -1;
+ GMainLoop* main_loop = loop;
- if(main_loop == NULL) {
- main_loop = g_main_loop_new(NULL, FALSE);
- }
+ if (main_loop == NULL) {
+ main_loop = g_main_loop_new(NULL, FALSE);
+ }
- void *context = zmq_init(1);
- ASSERT (context != NULL);
+ if (_g_singleton_for_publish)
+ __launch_thread(__publish_loop, _g_singleton_for_publish);
- if (_g_singleton_for_publish)
- {
- retval = __open_zmq_socket_for_publish(context, _g_singleton_for_publish);
- ASSERT(retval == 0);
- }
+ if (_g_singleton) {
+ ret = __open_router_fd(_g_singleton);
+ ASSERT(ret == 0);
- if (_g_singleton)
- {
- retval = __open_zmq_socket(context, _g_singleton);
- ASSERT(retval == 0);
- }
+ int i;
+ // launch worker threads in advance
+ for (i = 0; i < _g_singleton->workers_max_count; i++)
+ __launch_thread(__worker_loop, _g_singleton);
- __launch_worker(__main_loop, _g_singleton);
+ __launch_thread(__router_loop, _g_singleton);
+ __main_loop(_g_singleton);
+ }
- g_main_loop_run(main_loop);
+ g_main_loop_run(main_loop);
- if (_g_singleton)
- {
- __close_zmq_socket(_g_singleton);
- }
+ if (_g_singleton)
+ __close_router_fd(_g_singleton);
- if (_g_singleton_for_publish)
- {
- __close_zmq_socket_for_publish(_g_singleton_for_publish);
- }
+ if (_g_singleton_for_publish)
+ __stop_for_publish(_g_singleton_for_publish);
- if (zmq_term(context) == -1)
- WARNING("term error : %s", zmq_strerror(errno));
}
+
+API void pims_ipc_svc_set_client_disconnected_cb(pims_ipc_svc_client_disconnected_cb callback, void *user_data)
+{
+ if (_client_disconnected_cb.callback) {
+ ERROR("already registered");
+ return;
+ }
+ _client_disconnected_cb.callback = callback;
+ _client_disconnected_cb.user_data = user_data;
+}
+
+
#include <time.h>
#include <glib.h>
#include <stdint.h>
-#include <sys/types.h>
#include <pthread.h>
+#include <poll.h> // pollfds
+#include <sys/un.h> // sockaddr_un
+#include <sys/ioctl.h> // ioctl
+#include <sys/socket.h> //socket
+#include <sys/types.h>
+#include <sys/epoll.h> // epoll
+#include <sys/eventfd.h> // eventfd
+#include <fcntl.h>
-#include <pims-internal.h>
-#include <pims-socket.h>
-#include <pims-debug.h>
-#include <pims-ipc-data.h>
-#include <pims-ipc.h>
+#include "pims-internal.h"
+#include "pims-socket.h"
+#include "pims-debug.h"
+#include "pims-ipc-data.h"
+#include "pims-ipc-data-internal.h"
+#include "pims-ipc.h"
#define GET_CALL_SEQUNECE_NO(handle, sequence_no) do {\
- sequence_no = ++((handle)->call_sequence_no);\
+ sequence_no = ++((handle)->call_sequence_no);\
} while (0)
static pthread_mutex_t __gmutex = PTHREAD_MUTEX_INITIALIZER;
typedef enum
{
- PIMS_IPC_CALL_STATUS_READY = 0,
- PIMS_IPC_CALL_STATUS_IN_PROGRESS
+ PIMS_IPC_CALL_STATUS_READY = 0,
+ PIMS_IPC_CALL_STATUS_IN_PROGRESS
} pims_ipc_call_status_e;
typedef enum
{
- PIMS_IPC_MODE_REQ = 0,
- PIMS_IPC_MODE_SUB
+ PIMS_IPC_MODE_REQ = 0,
+ PIMS_IPC_MODE_SUB
} pims_ipc_mode_e;
typedef struct
{
- pid_t pid;
- void *context;
- unsigned int ref_cnt;
- GList *subscribe_handles;
-} pims_ipc_context_t;
-
-static pims_ipc_context_t *_g_singleton = NULL;
+ pims_ipc_subscribe_cb callback;
+ void * user_data;
+} pims_ipc_cb_s;
typedef struct
{
- pims_ipc_subscribe_cb callback;
- void * user_data;
-} pims_ipc_cb_t;
+ char *call_id;
+ pims_ipc_data_h *handle;
+}pims_ipc_subscribe_data_s;
typedef struct
{
- int fd;
- void *requester;
- char *service;
- char *id;
- GIOChannel *async_channel;
- guint async_source_id;
- pims_ipc_call_status_e call_status;
- unsigned int call_sequence_no;
- pims_ipc_call_async_cb call_async_callback;
- void *call_async_userdata;
- GHashTable *subscribe_cb_table;
-} pims_ipc_t;
-
-#define PIMS_IPC_SOCKET_BUFFER_SIZE 256
-static inline int __pims_zmq_msg_recv_by_handle(zmq_msg_t *msg, pims_ipc_t *handle, int flags)
+ int fd;
+ char *service;
+ char *id;
+ GIOChannel *async_channel;
+ guint async_source_id;
+ pthread_mutex_t call_status_mutex;
+ pims_ipc_call_status_e call_status;
+ unsigned int call_sequence_no;
+ pims_ipc_call_async_cb call_async_callback;
+ void *call_async_userdata;
+ pims_ipc_data_h dhandle_for_async_idler;
+
+ int subscribe_fd;
+ int epoll_stop_thread;
+ pthread_t io_thread;
+ GHashTable *subscribe_cb_table;
+
+ pthread_mutex_t data_queue_mutex;
+ GList *data_queue;
+} pims_ipc_s;
+
+static unsigned int ref_cnt;
+static GList *subscribe_handles;
+
+static void __sub_data_free(gpointer user_data)
{
- int ret = -1;
-
- while (1)
- {
- zmq_pollitem_t items[] = {
- {handle->requester, 0, ZMQ_POLLIN, 0},
- {NULL, handle->fd, ZMQ_POLLIN, 0}
- };
-
- if (zmq_poll(items, 2, -1) == -1)
- {
- if (errno == EINTR)
- continue;
-
- ERROR("poll error : %s", zmq_strerror(errno));
- break;
- }
-
- if (items[0].revents & ZMQ_POLLIN)
- {
- ret = zmq_msg_recv(msg, handle->requester, flags);
- if (ret == -1 && errno == EINTR)
- continue;
- break;
- }
-
- if (items[1].revents & ZMQ_POLLIN)
- {
- char buffer[PIMS_IPC_SOCKET_BUFFER_SIZE] = "";
-
- memset(buffer, 0x00, PIMS_IPC_SOCKET_BUFFER_SIZE);
- ret = read(handle->fd, (char *)buffer, PIMS_IPC_SOCKET_BUFFER_SIZE-1);
- ASSERT(ret <= 0);
-
- close(handle->fd);
- handle->fd = -1;
-
- if (handle->requester)
- zmq_close(handle->requester);
- handle->requester = NULL;
-
- errno = ETERM;
- ret = -1;
- break;
- }
- }
-
- return ret;
+ pims_ipc_subscribe_data_s *data = (pims_ipc_subscribe_data_s*)user_data;
+ pims_ipc_data_destroy(data->handle);
+ free(data->call_id);
+ free(data);
}
-static void __pims_ipc_free_handle(pims_ipc_t *handle)
+static void __pims_ipc_free_handle(pims_ipc_s *handle)
{
- pthread_mutex_lock(&__gmutex);
-
- g_free(handle->id);
- g_free(handle->service);
-
- if (handle->requester)
- zmq_close(handle->requester);
-
- if (handle->fd != -1)
- close(handle->fd);
-
- if (handle->async_channel)
- {
- // remove a subscriber handle from the golbal list
- if (_g_singleton)
- {
- _g_singleton->subscribe_handles = g_list_remove(_g_singleton->subscribe_handles, handle);
- VERBOSE("the count of subscribe handles = %d", g_list_length(_g_singleton->subscribe_handles));
- }
-
- g_source_remove(handle->async_source_id);
- g_io_channel_unref(handle->async_channel);
- }
-
- if (handle->subscribe_cb_table)
- g_hash_table_destroy(handle->subscribe_cb_table);
-
- g_free(handle);
-
- if (_g_singleton && --_g_singleton->ref_cnt <= 0)
- {
- if (zmq_term(_g_singleton->context) == -1)
- {
- WARNING("term error : %s", zmq_strerror(errno));
- }
- g_free(_g_singleton);
- _g_singleton = NULL;
- }
-
- pthread_mutex_unlock(&__gmutex);
+ pthread_mutex_lock(&__gmutex);
+
+ handle->epoll_stop_thread = true;
+
+ if (handle->fd != -1)
+ close(handle->fd);
+
+ if (handle->io_thread)
+ pthread_join(handle->io_thread, NULL);
+
+ g_free(handle->id);
+ g_free(handle->service);
+
+ if (handle->async_channel) {
+ // remove a subscriber handle from the golbal list
+ subscribe_handles = g_list_remove(subscribe_handles, handle);
+ VERBOSE("the count of subscribe handles = %d", g_list_length(subscribe_handles));
+
+ g_source_remove(handle->async_source_id);
+ g_io_channel_unref(handle->async_channel);
+ }
+
+ if (handle->subscribe_cb_table)
+ g_hash_table_destroy(handle->subscribe_cb_table);
+
+ pthread_mutex_lock(&handle->data_queue_mutex);
+ if (handle->data_queue) {
+ g_list_free_full(handle->data_queue, __sub_data_free);
+ }
+ pthread_mutex_unlock(&handle->data_queue_mutex);
+ pthread_mutex_destroy(&handle->data_queue_mutex);
+
+ if (handle->subscribe_fd != -1)
+ close(handle->subscribe_fd);
+
+ pthread_mutex_destroy(&handle->call_status_mutex);
+
+ g_free(handle);
+
+ if (--ref_cnt <= 0) {
+ if (subscribe_handles)
+ g_list_free(subscribe_handles);
+ subscribe_handles = NULL;
+ }
+
+ pthread_mutex_unlock(&__gmutex);
}
-static int __pims_ipc_receive_for_subscribe(pims_ipc_t *handle)
+static int __pims_ipc_receive_for_subscribe(pims_ipc_s *handle)
{
- gboolean is_valid = FALSE;
- int64_t more = 0;
- pims_ipc_data_h dhandle = NULL;
- pims_ipc_cb_t *cb_data = NULL;
-
- zmq_msg_t call_id_msg;
- zmq_msg_t data_msg;
-
- zmq_msg_init(&call_id_msg);
- zmq_msg_init(&data_msg);
-
- do {
- // recv call id
- if (__pims_zmq_msg_recv_by_handle(&call_id_msg, handle, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- break;
- }
-
- // find a callback by a call id
- cb_data = (pims_ipc_cb_t*)g_hash_table_lookup(handle->subscribe_cb_table, zmq_msg_data(&call_id_msg));
-
- size_t more_size = sizeof(more);
- zmq_getsockopt(handle->requester, ZMQ_RCVMORE, &more, &more_size);
- if (more)
- {
- if (__pims_zmq_msg_recv_by_handle(&data_msg, handle, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- break;
- }
-
- if (cb_data == NULL)
- {
- VERBOSE("unable to find %s", (char*)zmq_msg_data(&call_id_msg));
- is_valid = TRUE;
- break;
- }
-
- dhandle = pims_ipc_data_unmarshal_with_zmq(&data_msg);
- if (dhandle == NULL)
- {
- ERROR("unmarshal error");
- break;
- }
-
- cb_data->callback((pims_ipc_h)handle, dhandle, cb_data->user_data);
- }
-
- is_valid = TRUE;
- } while (0);
-
- zmq_msg_close(&call_id_msg);
- zmq_msg_close(&data_msg);
- if (dhandle)
- pims_ipc_data_destroy(dhandle);
-
- if (is_valid == FALSE)
- return -1;
- return 0;
+ pims_ipc_cb_s *cb_data = NULL;
+ uint64_t dummy;
+
+ do {
+ read_command(handle->subscribe_fd, &dummy);
+
+ pthread_mutex_lock(&handle->data_queue_mutex);
+ if (!handle->data_queue) {
+ pthread_mutex_unlock(&handle->data_queue_mutex);
+ break;
+ }
+
+ GList *cursor = g_list_first(handle->data_queue);
+ pims_ipc_subscribe_data_s *data = (pims_ipc_subscribe_data_s *)cursor->data;
+ if (data == NULL) {
+ pthread_mutex_unlock(&handle->data_queue_mutex);
+ break;
+ }
+
+ cb_data = (pims_ipc_cb_s*)g_hash_table_lookup(handle->subscribe_cb_table, data->call_id);
+ if (cb_data == NULL) {
+ VERBOSE("unable to find %s", call_id);
+ }
+ else
+ cb_data->callback((pims_ipc_h)handle, data->handle, cb_data->user_data);
+
+ handle->data_queue = g_list_delete_link(handle->data_queue, cursor);
+ __sub_data_free(data);
+ pthread_mutex_unlock(&handle->data_queue_mutex);
+ } while(1);
+
+ return 0;
}
static gboolean __pims_ipc_subscribe_handler(GIOChannel *src, GIOCondition condition, gpointer data)
{
- pims_ipc_t *handle = (pims_ipc_t *)data;
- uint32_t zmq_events = 0;
- size_t opt_len = 0;
- int rc = 0;
-
- VERBOSE("");
-
- pthread_mutex_lock(&__gmutex);
-
- // check if a subscriber handle is exists
- if (_g_singleton == NULL || g_list_find(_g_singleton->subscribe_handles, handle) == NULL)
- {
- DEBUG("No such handle that ID is %p", handle);
- pthread_mutex_unlock(&__gmutex);
- return FALSE;
- }
-
- opt_len = sizeof(uint32_t);
- while (1)
- {
- rc = zmq_getsockopt(handle->requester, ZMQ_EVENTS, &zmq_events, &opt_len);
- ASSERT(rc == 0);
- if (ZMQ_POLLIN & zmq_events) {
- __pims_ipc_receive_for_subscribe(handle);
- }
- else
- {
- break;
- }
- }
-
- pthread_mutex_unlock(&__gmutex);
-
- return TRUE;
+ pims_ipc_s *handle = (pims_ipc_s *)data;
+
+ VERBOSE("");
+
+ if (condition & G_IO_HUP)
+ return FALSE;
+
+ pthread_mutex_lock(&__gmutex);
+
+ // check if a subscriber handle is exists
+ if (g_list_find(subscribe_handles, handle) == NULL) {
+ ERROR("No such handle that ID is %p", handle);
+ pthread_mutex_unlock(&__gmutex);
+ return FALSE;
+ }
+
+ __pims_ipc_receive_for_subscribe(handle);
+
+ pthread_mutex_unlock(&__gmutex);
+
+ return TRUE;
}
static unsigned int __get_global_sequence_no()
{
- static unsigned int __gsequence_no = 0xffffffff;
+ static unsigned int __gsequence_no = 0xffffffff;
+
+ if (__gsequence_no == 0xffffffff)
+ __gsequence_no = (unsigned int)time(NULL);
+ else
+ __gsequence_no++;
+ return __gsequence_no;
+}
+
+static int __pims_ipc_send_identify(pims_ipc_s *handle)
+{
+ unsigned int sequence_no;
+ unsigned int client_id_len = strlen(handle->id);
+ unsigned int len = sizeof(unsigned int) // total size
+ + client_id_len + sizeof(unsigned int) // client_id
+ + sizeof(unsigned int) ; // seq_no
+
+ char buf[len+1];
+ int length = 0;
+ memset(buf, 0x0, len+1);
+
+ // total len
+ memcpy(buf, (void*)&len, sizeof(unsigned int));
+ length += sizeof(unsigned int);
+
+ // client_id
+ memcpy(buf+length, (void*)&(client_id_len), sizeof(unsigned int));
+ length += sizeof(unsigned int);
+ memcpy(buf+length, (void*)(handle->id), client_id_len);
+ length += client_id_len;
+
+ // seq_no
+ GET_CALL_SEQUNECE_NO(handle, sequence_no);
+ memcpy(buf+length, (void*)&(sequence_no), sizeof(unsigned int));
+ length += sizeof(unsigned int);
+
+ return socket_send(handle->fd, buf, length);
+}
+
+static int __pims_ipc_read_data(pims_ipc_s *handle, pims_ipc_data_h *data_out)
+{
+ int ret;
+ gboolean is_ok = FALSE;
+ int len = 0;
+ pims_ipc_data_h data = NULL;
+ unsigned int sequence_no = 0;
+ char *client_id = NULL;
+ char *call_id = NULL;
+ char *buf = NULL;
+
+ /* read the size of message. note that ioctl is non-blocking */
+ if (ioctl(handle->fd, FIONREAD, &len)) {
+ ERROR("ioctl failed: %d", errno);
+ return -1;
+ }
+
+ /* when server or client closed socket */
+ if (len == 0) {
+ ERROR("[IPC Socket] connection is closed");
+ return -1;
+ }
+
+ do {
+ unsigned int read_len = 0;
+ unsigned int total_len = 0;
+ unsigned int client_id_len = 0;
+ unsigned int call_id_len = 0;
+ unsigned int is_data = FALSE;
+
+ // get total_len
+ read_len = read(handle->fd, (void *)&total_len, sizeof(unsigned int));
+
+ // client_id
+ read_len += read(handle->fd, (void *)&(client_id_len), sizeof(unsigned int));
+ if (client_id_len > 0 && client_id_len < UINT_MAX-1) {
+ client_id = calloc(1, client_id_len+1);
+ if (client_id == NULL) {
+ ERROR("calloc fail");
+ break;
+ }
+ }
+ else
+ break;
+ ret = socket_recv(handle->fd, (void *)&(client_id), client_id_len);
+ if (ret < 0) { ERROR("socket_recv error"); break; }
+ read_len += ret;
+
+ // sequence no
+ read_len += read(handle->fd, (void *)&(sequence_no), sizeof(unsigned int));
+ if (total_len == read_len) {
+ // send identity
+ data = pims_ipc_data_create(0);
+ ret = pims_ipc_data_put(data, client_id, client_id_len);
+ if (ret != 0)
+ WARNING("pims_ipc_data_put fail(%d)", ret);
+ break;
+ }
+
+ read_len += read(handle->fd, (void *)&(call_id_len), sizeof(unsigned int));
+ if (call_id_len > 0 && call_id_len < UINT_MAX-1) {
+ call_id = calloc(1, call_id_len+1);
+ if (call_id == NULL) {
+ ERROR("calloc fail");
+ break;
+ }
+ }
+ else
+ break;
+
+ ret = socket_recv(handle->fd, (void *)&(call_id), call_id_len);
+ if (ret < 0) { ERROR("socket_recv error"); break; }
+ read_len += ret;
+
+ read_len += read(handle->fd, (void *)&(is_data), sizeof(unsigned int));
+ if (is_data) {
+ unsigned int data_len;
+ read_len += read(handle->fd, (void *)&(data_len), sizeof(unsigned int));
+ if (data_len > 0 && data_len < UINT_MAX-1) {
+ buf = calloc(1, data_len+1);
+ if (buf == NULL) {
+ ERROR("calloc fail");
+ break;
+ }
+ }
+ else
+ break;
+ ret = socket_recv(handle->fd, (void *)&(buf), data_len);
+ if (ret < 0) { ERROR("socket_recv error"); break; }
+ read_len += ret;
+
+ data = pims_ipc_data_steal_unmarshal(buf, data_len);
+ buf = NULL;
+ }
+
+ INFO("client_id :%s, call_id : %s, seq_no : %d", client_id, call_id, sequence_no);
+ } while(0);
+ free(client_id);
+ free(call_id);
+ free(buf);
+
+ if (sequence_no == handle->call_sequence_no) {
+ if (data_out != NULL) {
+ *data_out = data;
+ }
+ else if (data)
+ pims_ipc_data_destroy(data);
+ is_ok = TRUE;
+ }
+ else {
+ if (data)
+ pims_ipc_data_destroy(data);
+ VERBOSE("received an mismatched response (%x:%x)", handle->call_sequence_no, sequence_no);
+ }
+
+ if (is_ok)
+ return 0;
+
+ return -1;
+}
+
+static int __pims_ipc_receive(pims_ipc_s *handle, pims_ipc_data_h *data_out)
+{
+ int ret = -1;
+ struct pollfd *pollfds = (struct pollfd*) malloc (1 * sizeof (struct pollfd));
+
+ pollfds[0].fd = handle->fd;
+ pollfds[0].events = POLLIN | POLLERR | POLLHUP;
+
+ while(1) {
+ while(1) {
+ ret = poll(pollfds, 1, 1000);
+ if (ret == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) {
+ continue;
+ }
+ break;
+ }
+
+ if (ret > 0) {
+ if (pollfds[0].revents & (POLLERR|POLLHUP)) {
+ ERROR("Server disconnected");
+ ret = -1;
+ break;
+ }
+ if (pollfds[0].revents & POLLIN) {
+ ret = __pims_ipc_read_data(handle, data_out);
+ break;
+ }
+ }
+ }
+ free (pollfds);
+ return ret;
+}
+
+static int __open_subscribe_fd(pims_ipc_s *handle)
+{
+ // router inproc eventfd
+ int subscribe_fd = eventfd(0,0);
+ int flags;
+ int ret;
+
+ if (-1 == subscribe_fd) {
+ ERROR("eventfd error : %d", errno);
+ return -1;
+ }
+ VERBOSE("subscribe :%d\n", subscribe_fd);
+
+ flags = fcntl (subscribe_fd, F_GETFL, 0);
+ if (flags == -1)
+ flags = 0;
+ ret = fcntl (subscribe_fd, F_SETFL, flags | O_NONBLOCK);
+ VERBOSE("subscribe fcntl : %d\n", ret);
+
+ handle->subscribe_fd = subscribe_fd;
+ return 0;
+}
- if (__gsequence_no == 0xffffffff)
- __gsequence_no = (unsigned int)time(NULL);
- else
- __gsequence_no++;
- return __gsequence_no;
+static int __subscribe_data(pims_ipc_s * handle)
+{
+ int len;
+ int ret = -1;
+ char *call_id = NULL;
+ char *buf = NULL;
+ pims_ipc_data_h dhandle = NULL;
+
+ do {
+ /* read the size of message. note that ioctl is non-blocking */
+ if (ioctl(handle->fd, FIONREAD, &len)) {
+ ERROR("ioctl failed: %d", errno);
+ break;
+ }
+
+ /* when server or client closed socket */
+ if (len == 0) {
+ INFO("[IPC Socket] connection is closed");
+ break;
+ }
+
+ unsigned int read_len = 0;
+ unsigned int total_len = 0;
+ unsigned int call_id_len = 0;
+ unsigned int is_data = FALSE;
+
+ // get total_len
+ read_len = read(handle->fd, (void *)&total_len, sizeof(unsigned int));
+
+ // call_id
+ read_len += read(handle->fd, (void *)&(call_id_len), sizeof(unsigned int));
+ if (call_id_len > 0 && call_id_len < UINT_MAX-1) {
+ call_id = calloc(1, call_id_len+1);
+ if (call_id == NULL) {
+ ERROR("calloc fail");
+ break;
+ }
+ }
+ else
+ break;
+
+ ret = socket_recv(handle->fd, (void *)&(call_id), call_id_len);
+ if (ret < 0) { ERROR("socket_recv error"); break; }
+ read_len += ret;
+
+ // is_data
+ read_len += read(handle->fd, (void *)&(is_data), sizeof(unsigned int));
+
+ if (is_data) {
+ unsigned int data_len;
+ read_len += read(handle->fd, (void *)&(data_len), sizeof(unsigned int));
+ if (data_len > 0 && data_len < UINT_MAX-1) {
+ buf = calloc(1, data_len+1);
+ if (buf == NULL) {
+ ERROR("calloc fail");
+ break;
+ }
+ }
+ else
+ break;
+ ret = socket_recv(handle->fd, (void *)&(buf), data_len);
+ if (ret < 0) { ERROR("socket_recv error"); break; }
+ read_len += ret;
+
+ dhandle = pims_ipc_data_steal_unmarshal(buf, data_len);
+ buf = NULL;
+
+ pims_ipc_subscribe_data_s *sub_data = (pims_ipc_subscribe_data_s *)calloc(1, sizeof(pims_ipc_subscribe_data_s));
+ sub_data->handle = dhandle;
+ sub_data->call_id = call_id;
+ call_id = NULL;
+
+ pthread_mutex_lock(&handle->data_queue_mutex);
+ handle->data_queue = g_list_append(handle->data_queue, sub_data);
+ pthread_mutex_unlock(&handle->data_queue_mutex);
+ write_command(handle->subscribe_fd, 1);
+ }
+ ret = 0;
+ }while(0);
+
+ free(call_id);
+ free(buf);
+ return ret;
+}
+
+static void* __io_thread(void *data)
+{
+ pims_ipc_s *handle = data;
+ struct epoll_event ev = {0};
+ int ret;
+ int epfd;
+
+ epfd = epoll_create(MAX_EPOLL_EVENT);
+
+ ev.events = EPOLLIN | EPOLLHUP;
+ ev.data.fd = handle->fd;
+
+ ret = epoll_ctl(epfd, EPOLL_CTL_ADD, handle->fd, &ev);
+ WARN_IF(ret != 0, "listen error :%d", ret);
+
+ while (!handle->epoll_stop_thread) {
+ int i = 0;
+ struct epoll_event events[MAX_EPOLL_EVENT] = {{0}, };
+ int event_num = epoll_wait(epfd, events, MAX_EPOLL_EVENT, 50);
+
+ if (handle->epoll_stop_thread)
+ break;
+
+ if (event_num == -1) {
+ if (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK) {
+ ERROR("errno:%d\n", errno);
+ break;
+ }
+ }
+
+ for (i = 0; i < event_num; i++) {
+ if (events[i].events & EPOLLHUP) {
+ ERROR("server fd closed");
+ handle->epoll_stop_thread = true;
+ break;
+ }
+
+ if (events[i].events & EPOLLIN) {
+ if(__subscribe_data(handle) < 0)
+ break;
+ }
+ }
+ }
+
+ close(epfd);
+
+ pthread_exit(NULL);
}
static pims_ipc_h __pims_ipc_create(char *service, pims_ipc_mode_e mode)
{
- pims_ipc_context_t *ghandle = NULL;
- pims_ipc_t *handle = NULL;
- pid_t pid = 0;
- void *context = NULL;
- void *requester = NULL;
- char *path = NULL;
- gboolean is_ok = FALSE;
-
- pthread_mutex_lock(&__gmutex);
-
- do {
- if (_g_singleton == NULL)
- {
- ghandle = g_new0(pims_ipc_context_t, 1);
- if (ghandle == NULL)
- {
- ERROR("Failed to allocation");
- break;
- }
-
- pid = getpid();
- ghandle->pid = pid;
- VERBOSE("The PID of the current process is %d.", pid);
-
- context = zmq_init(1);
- if (!context)
- {
- ERROR("init error : %s", zmq_strerror(errno));
- break;
- }
- ghandle->context = context;
- ghandle->ref_cnt = 1;
- _g_singleton = ghandle;
- }
- else
- {
- ghandle = _g_singleton;
- ghandle->ref_cnt++;
- pid = ghandle->pid;
- context = ghandle->context;
- }
-
- VERBOSE("Create %d th..", ghandle->ref_cnt);
-
- handle = g_new0(pims_ipc_t, 1);
- if (handle == NULL)
- {
- ERROR("Failed to allocation");
- break;
- }
- handle->fd = -1;
-
- handle->service = g_strdup(service);
- handle->id = g_strdup_printf("%x:%x", pid, __get_global_sequence_no());
-
- if (mode == PIMS_IPC_MODE_REQ)
- {
- path = g_strdup_printf("%s-%s", handle->service, PIMS_IPC_MONITOR_PATH);
- handle->fd = _client_socket_init(path, handle->id);
- if (handle->fd == -1)
- {
- g_free(path);
- break;
- }
- g_free(path);
-
- requester = zmq_socket(context, ZMQ_REQ);
- if (!requester)
- {
- ERROR("socket error : %s", zmq_strerror(errno));
- break;
- }
- if (zmq_setsockopt(requester, ZMQ_IDENTITY, handle->id, strlen(handle->id) + 1) != 0)
- {
- ERROR("setsockopt error : %s", zmq_strerror(errno));
- break;
- }
- handle->requester = requester;
-
- path = g_strdup_printf("ipc://%s", handle->service);
- if (zmq_connect(requester, path) != 0)
- {
- ERROR("connect error : %s", zmq_strerror(errno));
- g_free(path);
- break;
- }
- g_free(path);
-
- handle->call_sequence_no = (unsigned int)time(NULL);
- if (pims_ipc_call(handle, PIMS_IPC_MODULE_INTERNAL, PIMS_IPC_FUNCTION_CREATE, NULL, NULL) != 0)
- {
- WARNING("pims_ipc_call(PIMS_IPC_FUNCTION_CREATE) failed");
- }
- }
- else
- {
- requester = zmq_socket(context, ZMQ_SUB);
- if (!requester)
- {
- ERROR("socket error : %s", zmq_strerror(errno));
- break;
- }
- if (zmq_setsockopt(requester, ZMQ_SUBSCRIBE, "", 0) != 0)
- {
- ERROR("setsockopt error : %s", zmq_strerror(errno));
- break;
- }
- handle->requester = requester;
-
- path = g_strdup_printf("ipc://%s", handle->service);
- if (zmq_connect(requester, path) != 0)
- {
- ERROR("connect error : %s", zmq_strerror(errno));
- g_free(path);
- break;
- }
- g_free(path);
-
- int fd = -1;
- size_t opt_len = sizeof(int);
- int rc = zmq_getsockopt(handle->requester, ZMQ_FD, &fd, &opt_len);
- ASSERT(rc == 0);
-
- handle->async_channel = g_io_channel_unix_new(fd);
- if (!handle->async_channel)
- {
- ERROR("g_io_channel_unix_new error");
- break;
- }
-
- guint source_id = 0;
- source_id = g_io_add_watch(handle->async_channel, G_IO_IN, __pims_ipc_subscribe_handler, handle);
- handle->async_source_id = source_id;
- handle->subscribe_cb_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
- ASSERT(handle->subscribe_cb_table);
-
- // add a subscriber handle to the global list
- ghandle->subscribe_handles = g_list_append(ghandle->subscribe_handles, handle);
- VERBOSE("the count of subscribe handles = %d", g_list_length(ghandle->subscribe_handles));
- }
-
- is_ok = TRUE;
- VERBOSE("A new handle is created : %s, %s", handle->service, handle->id);
- } while(0);
-
- pthread_mutex_unlock(&__gmutex);
-
- if (FALSE == is_ok)
- {
- if (handle)
- {
- __pims_ipc_free_handle(handle);
- handle = NULL;
- }
- }
-
- return handle;
+ pims_ipc_s *handle = NULL;
+ gboolean is_ok = FALSE;
+
+ pthread_mutex_lock(&__gmutex);
+
+ do {
+ struct sockaddr_un server_addr;
+ int ret;
+
+ ref_cnt++;
+ VERBOSE("Create %d th..", ref_cnt);
+
+ handle = g_new0(pims_ipc_s, 1);
+ if (handle == NULL) {
+ ERROR("Failed to allocation");
+ break;
+ }
+
+ handle->subscribe_fd = -1;
+ handle->io_thread = 0;
+ handle->service = g_strdup(service);
+ handle->id = g_strdup_printf("%x:%x", getpid(), __get_global_sequence_no());
+ handle->fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (handle->fd < 0) {
+ ERROR("socket error : %d, errno: %d", handle->fd, errno);
+ break;
+ }
+ int flags = fcntl (handle->fd, F_GETFL, 0);
+ if (flags == -1)
+ flags = 0;
+ ret = fcntl (handle->fd, F_SETFL, flags | O_NONBLOCK);
+ VERBOSE("socket fcntl : %d\n", ret);
+
+ pthread_mutex_init(&handle->call_status_mutex, 0);
+
+ pthread_mutex_lock(&handle->call_status_mutex);
+ handle->call_status = PIMS_IPC_CALL_STATUS_READY;
+ pthread_mutex_unlock(&handle->call_status_mutex);
+
+ bzero(&server_addr, sizeof(server_addr));
+ server_addr.sun_family = AF_UNIX;
+ snprintf(server_addr.sun_path, sizeof(server_addr.sun_path), "%s", handle->service);
+
+ ret = connect(handle->fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
+ if (ret != 0) {
+ ERROR("connect error : %d, errno: %d", ret, errno);
+ break;
+ }
+ VERBOSE("connect to server : socket:%s, client_sock:%d, %d\n", handle->service, handle->fd, ret);
+
+ if (mode == PIMS_IPC_MODE_REQ) {
+ handle->call_sequence_no = (unsigned int)time(NULL);
+ ret = __pims_ipc_send_identify(handle);
+ if (ret < 0) {
+ ERROR("__pims_ipc_send_identify error");
+ break;
+ }
+ __pims_ipc_receive(handle, NULL);
+
+ if (pims_ipc_call(handle, PIMS_IPC_MODULE_INTERNAL, PIMS_IPC_FUNCTION_CREATE, NULL, NULL) != 0) {
+ WARNING("pims_ipc_call(PIMS_IPC_FUNCTION_CREATE) failed");
+ }
+ }
+ else {
+ handle->epoll_stop_thread = false;
+ pthread_mutex_init(&handle->data_queue_mutex, 0);
+
+ pthread_mutex_lock(&handle->data_queue_mutex);
+ handle->data_queue = NULL;
+ pthread_mutex_unlock(&handle->data_queue_mutex);
+
+ ret = __open_subscribe_fd(handle);
+ if (ret < 0)
+ break;
+
+ pthread_t worker;
+ ret = pthread_create(&worker, NULL, __io_thread, handle);
+ if (ret != 0)
+ break;
+ handle->io_thread = worker;
+
+ GIOChannel *async_channel = g_io_channel_unix_new(handle->subscribe_fd);
+ if (!async_channel) {
+ ERROR("g_io_channel_unix_new error");
+ break;
+ }
+ handle->async_channel = async_channel;
+ handle->async_source_id = g_io_add_watch(handle->async_channel, G_IO_IN|G_IO_HUP, __pims_ipc_subscribe_handler, handle);
+ handle->subscribe_cb_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ ASSERT(handle->subscribe_cb_table);
+
+ // add a subscriber handle to the global list
+ subscribe_handles = g_list_append(subscribe_handles, handle);
+ VERBOSE("the count of subscribe handles = %d", g_list_length(subscribe_handles));
+ }
+
+ is_ok = TRUE;
+ VERBOSE("A new handle is created : %s, %s", handle->service, handle->id);
+ } while(0);
+
+ pthread_mutex_unlock(&__gmutex);
+
+ if (FALSE == is_ok) {
+ if (handle) {
+ __pims_ipc_free_handle(handle);
+ handle = NULL;
+ }
+ }
+
+ return handle;
}
API pims_ipc_h pims_ipc_create(char *service)
{
- return __pims_ipc_create(service, PIMS_IPC_MODE_REQ);
+ return __pims_ipc_create(service, PIMS_IPC_MODE_REQ);
}
API pims_ipc_h pims_ipc_create_for_subscribe(char *service)
{
- return __pims_ipc_create(service, PIMS_IPC_MODE_SUB);
+ return __pims_ipc_create(service, PIMS_IPC_MODE_SUB);
}
static void __pims_ipc_destroy(pims_ipc_h ipc, pims_ipc_mode_e mode)
{
- pims_ipc_t *handle = (pims_ipc_t *)ipc;
+ pims_ipc_s *handle = (pims_ipc_s *)ipc;
- if (mode == PIMS_IPC_MODE_REQ)
- {
- if (pims_ipc_call(handle, PIMS_IPC_MODULE_INTERNAL, PIMS_IPC_FUNCTION_DESTROY, NULL, NULL) != 0)
- {
- WARNING("pims_ipc_call(PIMS_IPC_FUNCTION_DESTROY) failed");
- }
- }
+ if (mode == PIMS_IPC_MODE_REQ) {
+ if (pims_ipc_call(handle, PIMS_IPC_MODULE_INTERNAL, PIMS_IPC_FUNCTION_DESTROY, NULL, NULL) != 0) {
+ WARNING("pims_ipc_call(PIMS_IPC_FUNCTION_DESTROY) failed");
+ }
+ }
- __pims_ipc_free_handle(handle);
+ if (handle)
+ __pims_ipc_free_handle(handle);
}
API void pims_ipc_destroy(pims_ipc_h ipc)
{
- __pims_ipc_destroy(ipc, PIMS_IPC_MODE_REQ);
+ __pims_ipc_destroy(ipc, PIMS_IPC_MODE_REQ);
}
API void pims_ipc_destroy_for_subscribe(pims_ipc_h ipc)
{
- __pims_ipc_destroy(ipc, PIMS_IPC_MODE_SUB);
+ __pims_ipc_destroy(ipc, PIMS_IPC_MODE_SUB);
}
-static void __pims_ipc_data_free_cb(void *data, void *hint)
+static int __pims_ipc_send(pims_ipc_s *handle, char *module, char *function, pims_ipc_data_h data_in)
{
- if (hint)
- g_free(hint);
+ int ret = -1;
+ unsigned int sequence_no = 0;
+ gchar *call_id = PIMS_IPC_MAKE_CALL_ID(module, function);
+ unsigned int call_id_len = strlen(call_id);
+ pims_ipc_data_s *data = NULL;
+ unsigned int is_data = FALSE;
+ unsigned int client_id_len = strlen(handle->id);
+ int length = 0;
+
+ GET_CALL_SEQUNECE_NO(handle, sequence_no);
+
+ int len = sizeof(unsigned int) // total size
+ + client_id_len + sizeof(unsigned int) // client_id
+ + sizeof(unsigned int) // seq_no
+ + call_id_len + sizeof(unsigned int) // call_id
+ + sizeof(unsigned int); // is data
+
+ int total_len = len;
+
+ if (data_in) {
+ is_data = TRUE;
+ data = (pims_ipc_data_s*)data_in;
+ len += sizeof(unsigned int);
+ total_len = len + data->buf_size;
+ }
+
+ INFO("len : %d, client_id : %s, call_id : %s, seq_no :%d", len, handle->id, call_id, sequence_no);
+
+ char buf[len+1];
+
+ memset(buf, 0x0, len+1);
+
+ memcpy(buf, (void*)&total_len, sizeof(unsigned int));
+ length += sizeof(unsigned int);
+
+ // client_id
+ client_id_len = strlen(handle->id);
+ memcpy(buf+length, (void*)&(client_id_len), sizeof(unsigned int));
+ length += sizeof(unsigned int);
+ memcpy(buf+length, (void*)(handle->id), client_id_len);
+ length += client_id_len;
+
+ // seq_no
+ memcpy(buf+length, (void*)&(sequence_no), sizeof(unsigned int));
+ length += sizeof(unsigned int);
+
+ // call id
+ memcpy(buf+length, (void*)&(call_id_len), sizeof(unsigned int));
+ length += sizeof(unsigned int);
+ memcpy(buf+length, (void*)(call_id), call_id_len);
+ length += call_id_len;
+ g_free(call_id);
+
+ // is_data
+ memcpy(buf+length, (void*)&(is_data), sizeof(unsigned int));
+ length += sizeof(unsigned int);
+
+ if (is_data) {
+ memcpy(buf+length, (void*)&(data->buf_size), sizeof(unsigned int));
+ length += sizeof(unsigned int);
+
+ ret = socket_send(handle->fd, buf, length);
+ if (ret > 0)
+ ret = socket_send_data(handle->fd, data->buf, data->buf_size);
+ }
+ else {
+ ret = socket_send(handle->fd, buf, length);
+ }
+
+ if (ret < 0)
+ return -1;
+
+ return 0;
}
-static int __pims_ipc_send(pims_ipc_t *handle, char *module, char *function, pims_ipc_h data_in)
+API int pims_ipc_call(pims_ipc_h ipc, char *module, char *function, pims_ipc_data_h data_in,
+ pims_ipc_data_h *data_out)
{
- gboolean is_valid = FALSE;
- unsigned int sequence_no = 0;
- gchar *call_id = PIMS_IPC_MAKE_CALL_ID(module, function);
-
- // init messages
- zmq_msg_t sequence_no_msg;
- zmq_msg_t call_id_msg;
- zmq_msg_t data_in_msg;
-
- zmq_msg_init_size(&sequence_no_msg, sizeof(unsigned int));
- GET_CALL_SEQUNECE_NO(handle, sequence_no);
- memcpy(zmq_msg_data(&sequence_no_msg), &(sequence_no), sizeof(unsigned int));
-
- zmq_msg_init_data(&call_id_msg, call_id, strlen(call_id) + 1, __pims_ipc_data_free_cb, call_id);
- VERBOSE("call id = %s", (char*)zmq_msg_data(&call_id_msg));
-
- zmq_msg_init(&data_in_msg);
-
- do {
- // send sequence no
- if (_pims_zmq_msg_send(&sequence_no_msg, handle->requester, ZMQ_SNDMORE) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- break;
- }
-
- if (data_in == NULL)
- {
- // send call id
- if (_pims_zmq_msg_send(&call_id_msg, handle->requester, 0) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- break;
- }
- }
- else
- {
- // send call id
- if (_pims_zmq_msg_send(&call_id_msg, handle->requester, ZMQ_SNDMORE) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- break;
- }
-
- // marshal data
- if (pims_ipc_data_marshal_with_zmq(data_in, &data_in_msg) != 0)
- {
- ERROR("marshal error");
- break;
- }
-
- VERBOSE("the size of sending data = %d", zmq_msg_size(&data_in_msg));
-
- // send data
- if (_pims_zmq_msg_send(&data_in_msg, handle->requester, 0) == -1)
- {
- ERROR("send error : %s", zmq_strerror(errno));
- break;
- }
- }
-
- is_valid = TRUE;
- } while (0);
-
- zmq_msg_close(&sequence_no_msg);
- zmq_msg_close(&call_id_msg);
- zmq_msg_close(&data_in_msg);
-
- if (is_valid == FALSE)
- return -1;
- return 0;
-}
+ pims_ipc_s *handle = (pims_ipc_s *)ipc;
-static int __pims_ipc_receive(pims_ipc_t *handle, pims_ipc_data_h *data_out)
-{
- gboolean is_ok = FALSE;
- gboolean is_valid = FALSE;
- int64_t more = 0;
- pims_ipc_data_h dhandle = NULL;
- unsigned int sequence_no = 0;
-
- zmq_msg_t sequence_no_msg;
- zmq_msg_t call_id_msg;
- zmq_msg_t data_out_msg;
-
- while (1)
- {
- is_valid = FALSE;
- more = 0;
-
- zmq_msg_init(&sequence_no_msg);
- zmq_msg_init(&call_id_msg);
- zmq_msg_init(&data_out_msg);
-
- do {
- // recv sequence no
- if (__pims_zmq_msg_recv_by_handle(&sequence_no_msg, handle, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- break;
- }
- memcpy(&sequence_no, zmq_msg_data(&sequence_no_msg), sizeof(unsigned int));
-
- // recv call id
- if (__pims_zmq_msg_recv_by_handle(&call_id_msg, handle, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- break;
- }
-
- size_t more_size = sizeof(more);
- zmq_getsockopt(handle->requester, ZMQ_RCVMORE, &more, &more_size);
- if (more)
- {
- if (__pims_zmq_msg_recv_by_handle(&data_out_msg, handle, 0) == -1)
- {
- ERROR("recv error : %s", zmq_strerror(errno));
- break;
- }
- dhandle = pims_ipc_data_unmarshal_with_zmq(&data_out_msg);
- if (dhandle == NULL)
- {
- ERROR("unmarshal error");
- break;
- }
-
- if (sequence_no == handle->call_sequence_no)
- {
- if (data_out != NULL)
- *data_out = dhandle;
- is_ok = TRUE;
- }
- else
- {
- pims_ipc_data_destroy(dhandle);
- DEBUG("received an mismatched response (%x:%x)", handle->call_sequence_no, sequence_no);
- }
- }
- else
- {
- if (sequence_no == handle->call_sequence_no)
- is_ok = TRUE;
- }
-
- is_valid = TRUE;
- } while (0);
-
- zmq_msg_close(&sequence_no_msg);
- zmq_msg_close(&call_id_msg);
- zmq_msg_close(&data_out_msg);
-
- if (is_ok)
- return 0;
-
- if (is_valid == FALSE)
- return -1;
- }
-
- return -1;
+
+ if (ipc == NULL) {
+ ERROR("invalid handle : %p", ipc);
+ return -1;
+ }
+
+ if (!module || !function) {
+ ERROR("invalid argument");
+ return -1;
+ }
+
+ pthread_mutex_lock(&handle->call_status_mutex);
+ if (handle->call_status != PIMS_IPC_CALL_STATUS_READY) {
+ pthread_mutex_unlock(&handle->call_status_mutex);
+ ERROR("the previous call is in progress : %p", ipc);
+ return -1;
+ }
+ pthread_mutex_unlock(&handle->call_status_mutex);
+
+
+ if (__pims_ipc_send(handle, module, function, data_in) != 0) {
+ return -1;
+ }
+
+ if (__pims_ipc_receive(handle, data_out) != 0) {
+ return -1;
+ }
+
+ return 0;
}
-API int pims_ipc_call(pims_ipc_h ipc, char *module, char *function, pims_ipc_data_h data_in,
- pims_ipc_data_h *data_out)
+static gboolean __call_async_idler_cb(gpointer data)
{
- pims_ipc_t *handle = (pims_ipc_t *)ipc;
-
-
- if (ipc == NULL)
- {
- ERROR("invalid handle : %p", ipc);
- return -1;
- }
-
- if (!module || !function)
- {
- ERROR("invalid argument");
- return -1;
- }
-
- if (handle->call_status != PIMS_IPC_CALL_STATUS_READY)
- {
- ERROR("the previous call is in progress : %p", ipc);
- return -1;
- }
-
- if (__pims_ipc_send(handle, module, function, data_in) != 0)
- {
- return -1;
- }
-
- if (__pims_ipc_receive(handle, data_out) != 0)
- {
- return -1;
- }
-
- return 0;
+ VERBOSE("");
+
+ pims_ipc_s *handle = (pims_ipc_s *)data;
+ ASSERT(handle);
+ ASSERT(handle->dhandle_for_async_idler);
+ pims_ipc_data_h dhandle = handle->dhandle_for_async_idler;
+ handle->dhandle_for_async_idler = NULL;
+
+ pthread_mutex_lock(&handle->call_status_mutex);
+ handle->call_status = PIMS_IPC_CALL_STATUS_READY;
+ pthread_mutex_unlock(&handle->call_status_mutex);
+
+ handle->call_async_callback((pims_ipc_h)handle, dhandle, handle->call_async_userdata);
+ pims_ipc_data_destroy(dhandle);
+
+ return FALSE;
}
static gboolean __pims_ipc_call_async_handler(GIOChannel *src, GIOCondition condition, gpointer data)
{
- pims_ipc_t *handle = (pims_ipc_t *)data;
- uint32_t zmq_events = 0;
- size_t opt_len = 0;
- int rc = 0;
-
- VERBOSE("");
-
- opt_len = sizeof(uint32_t);
- while (1)
- {
- rc = zmq_getsockopt(handle->requester, ZMQ_EVENTS, &zmq_events, &opt_len);
- ASSERT(rc == 0);
- if (ZMQ_POLLIN & zmq_events) {
- pims_ipc_data_h dhandle = NULL;
- if (__pims_ipc_receive(handle, &dhandle) == 0)
- {
- VERBOSE("call status = %d", handle->call_status);
- if (handle->call_status != PIMS_IPC_CALL_STATUS_IN_PROGRESS)
- {
- pims_ipc_data_destroy(dhandle);
- }
- else
- {
- handle->call_status = PIMS_IPC_CALL_STATUS_READY;
- handle->call_async_callback((pims_ipc_h)handle, dhandle, handle->call_async_userdata);
- pims_ipc_data_destroy(dhandle);
- }
- }
- }
- else
- {
- break;
- }
- }
-
- return FALSE;
+ pims_ipc_s *handle = (pims_ipc_s *)data;
+ pims_ipc_data_h dhandle = NULL;
+
+ if (__pims_ipc_receive(handle, &dhandle) == 0) {
+ VERBOSE("call status = %d", handle->call_status);
+
+ pthread_mutex_lock(&handle->call_status_mutex);
+ if (handle->call_status != PIMS_IPC_CALL_STATUS_IN_PROGRESS) {
+ pthread_mutex_unlock(&handle->call_status_mutex);
+ pims_ipc_data_destroy(dhandle);
+ }
+ else {
+ pthread_mutex_unlock(&handle->call_status_mutex);
+ if (src == NULL) { // A response is arrived too quickly
+ handle->dhandle_for_async_idler = dhandle;
+ g_idle_add(__call_async_idler_cb, handle);
+ }
+ else {
+ pthread_mutex_lock(&handle->call_status_mutex);
+ handle->call_status = PIMS_IPC_CALL_STATUS_READY;
+ pthread_mutex_unlock(&handle->call_status_mutex);
+
+ handle->call_async_callback((pims_ipc_h)handle, dhandle, handle->call_async_userdata);
+ pims_ipc_data_destroy(dhandle);
+ }
+ }
+ }
+ return FALSE;
}
API int pims_ipc_call_async(pims_ipc_h ipc, char *module, char *function, pims_ipc_data_h data_in,
- pims_ipc_call_async_cb callback, void *userdata)
+ pims_ipc_call_async_cb callback, void *userdata)
{
- pims_ipc_t *handle = (pims_ipc_t *)ipc;
- guint source_id = 0;
-
- if (ipc == NULL)
- {
- ERROR("invalid handle : %p", ipc);
- return -1;
- }
-
- if (!module || !function || !callback)
- {
- ERROR("invalid argument");
- return -1;
- }
-
- if (handle->call_status != PIMS_IPC_CALL_STATUS_READY)
- {
- ERROR("the previous call is in progress : %p", ipc);
- return -1;
- }
-
- handle->call_status = PIMS_IPC_CALL_STATUS_IN_PROGRESS;
- handle->call_async_callback = callback;
- handle->call_async_userdata = userdata;
-
- // add a callback for GIOChannel
- if (!handle->async_channel)
- {
- int fd = -1;
- size_t opt_len = sizeof(int);
- int rc = zmq_getsockopt(handle->requester, ZMQ_FD, &fd, &opt_len);
- ASSERT(rc == 0);
-
- handle->async_channel = g_io_channel_unix_new(fd);
- if (!handle->async_channel)
- {
- ERROR("g_io_channel_unix_new error");
- return -1;
- }
- }
-
- source_id = g_io_add_watch(handle->async_channel, G_IO_IN, __pims_ipc_call_async_handler, handle);
- handle->async_source_id = source_id;
-
- if (__pims_ipc_send(handle, module, function, data_in) != 0)
- {
- g_source_remove(source_id);
- return -1;
- }
-
- uint32_t zmq_events = 0;
- size_t opt_len = sizeof(uint32_t);
- int rc = 0;
- rc = zmq_getsockopt(handle->requester, ZMQ_EVENTS, &zmq_events, &opt_len);
- ASSERT(rc == 0);
-
- return 0;
+ pims_ipc_s *handle = (pims_ipc_s *)ipc;
+ guint source_id = 0;
+
+ if (ipc == NULL) {
+ ERROR("invalid handle : %p", ipc);
+ return -1;
+ }
+
+ if (!module || !function || !callback) {
+ ERROR("invalid argument");
+ return -1;
+ }
+
+ pthread_mutex_lock(&handle->call_status_mutex);
+ if (handle->call_status != PIMS_IPC_CALL_STATUS_READY) {
+ pthread_mutex_unlock(&handle->call_status_mutex);
+ ERROR("the previous call is in progress : %p", ipc);
+ return -1;
+ }
+ pthread_mutex_unlock(&handle->call_status_mutex);
+
+ pthread_mutex_lock(&handle->call_status_mutex);
+ handle->call_status = PIMS_IPC_CALL_STATUS_IN_PROGRESS;
+ pthread_mutex_unlock(&handle->call_status_mutex);
+
+ handle->call_async_callback = callback;
+ handle->call_async_userdata = userdata;
+
+ // add a callback for GIOChannel
+ if (!handle->async_channel) {
+ handle->async_channel = g_io_channel_unix_new(handle->fd);
+ if (!handle->async_channel) {
+ ERROR("g_io_channel_unix_new error");
+ return -1;
+ }
+ }
+
+ source_id = g_io_add_watch(handle->async_channel, G_IO_IN, __pims_ipc_call_async_handler, handle);
+ handle->async_source_id = source_id;
+
+ if (__pims_ipc_send(handle, module, function, data_in) != 0) {
+ g_source_remove(source_id);
+ return -1;
+ }
+
+ __pims_ipc_call_async_handler(NULL, G_IO_NVAL, handle);
+
+ return 0;
}
API bool pims_ipc_is_call_in_progress(pims_ipc_h ipc)
{
- pims_ipc_t *handle = (pims_ipc_t *)ipc;
-
- if (ipc == NULL)
- {
- ERROR("invalid handle : %p", ipc);
- return false;
- }
-
- if (handle->call_status == PIMS_IPC_CALL_STATUS_IN_PROGRESS)
- return true;
- else
- return false;
+ int ret;
+ pims_ipc_s *handle = (pims_ipc_s *)ipc;
+
+ if (ipc == NULL) {
+ ERROR("invalid handle : %p", ipc);
+ return false;
+ }
+
+ pthread_mutex_lock(&handle->call_status_mutex);
+ if (handle->call_status == PIMS_IPC_CALL_STATUS_IN_PROGRESS)
+ ret = true;
+ else
+ ret = false;
+ pthread_mutex_unlock(&handle->call_status_mutex);
+ return ret;
}
API int pims_ipc_subscribe(pims_ipc_h ipc, char *module, char *event, pims_ipc_subscribe_cb callback, void *userdata)
{
- gchar *call_id = NULL;
- pims_ipc_cb_t *cb_data = NULL;
- pims_ipc_t *handle = (pims_ipc_t *)ipc;
-
- if (ipc == NULL || handle->subscribe_cb_table == NULL)
- {
- ERROR("invalid handle : %p", ipc);
- return -1;
- }
-
- if (!module || !event || !callback)
- {
- ERROR("invalid argument");
- return -1;
- }
-
- cb_data = g_new0(pims_ipc_cb_t, 1);
- call_id = PIMS_IPC_MAKE_CALL_ID(module, event);
-
- VERBOSE("subscribe cb id[%s]", call_id);
- cb_data->callback = callback;
- cb_data->user_data = userdata;
- g_hash_table_insert(handle->subscribe_cb_table, call_id, cb_data);
-
- return 0;
+ gchar *call_id = NULL;
+ pims_ipc_cb_s *cb_data = NULL;
+ pims_ipc_s *handle = (pims_ipc_s *)ipc;
+
+ if (ipc == NULL || handle->subscribe_cb_table == NULL) {
+ ERROR("invalid handle : %p", ipc);
+ return -1;
+ }
+
+ if (!module || !event || !callback) {
+ ERROR("invalid argument");
+ return -1;
+ }
+
+ cb_data = g_new0(pims_ipc_cb_s, 1);
+ call_id = PIMS_IPC_MAKE_CALL_ID(module, event);
+
+ VERBOSE("subscribe cb id[%s]", call_id);
+ cb_data->callback = callback;
+ cb_data->user_data = userdata;
+ g_hash_table_insert(handle->subscribe_cb_table, call_id, cb_data);
+
+ return 0;
}
API int pims_ipc_unsubscribe(pims_ipc_h ipc, char *module, char *event)
{
- gchar *call_id = NULL;
- pims_ipc_t *handle = (pims_ipc_t *)ipc;
-
- if (ipc == NULL || handle->subscribe_cb_table == NULL)
- {
- ERROR("invalid handle : %p", ipc);
- return -1;
- }
-
- if (!module || !event)
- {
- ERROR("invalid argument");
- return -1;
- }
-
- call_id = PIMS_IPC_MAKE_CALL_ID(module, event);
-
- VERBOSE("unsubscribe cb id[%s]", call_id);
-
- if (g_hash_table_remove(handle->subscribe_cb_table, call_id) != TRUE)
- {
- ERROR("g_hash_table_remove error");
- g_free(call_id);
- return -1;
- }
-
- g_free(call_id);
- return 0;
+ gchar *call_id = NULL;
+ pims_ipc_s *handle = (pims_ipc_s *)ipc;
+
+ if (ipc == NULL || handle->subscribe_cb_table == NULL) {
+ ERROR("invalid handle : %p", ipc);
+ return -1;
+ }
+
+ if (!module || !event) {
+ ERROR("invalid argument");
+ return -1;
+ }
+
+ call_id = PIMS_IPC_MAKE_CALL_ID(module, event);
+
+ VERBOSE("unsubscribe cb id[%s]", call_id);
+
+ if (g_hash_table_remove(handle->subscribe_cb_table, call_id) != TRUE) {
+ ERROR("g_hash_table_remove error");
+ g_free(call_id);
+ return -1;
+ }
+
+ g_free(call_id);
+ return 0;
}
+
* limitations under the License.
*/
-
-#ifndef _NON_SLP
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/un.h>
-#include <systemd/sd-daemon.h>
-#include <pims-internal.h>
-#include <pims-debug.h>
-#include <pims-socket.h>
+#include "pims-internal.h"
+#include "pims-debug.h"
+#include "pims-socket.h"
-typedef struct
-{
- int sockfd;
- server_socket_client_closed_cb callback;
- void *user_data;
- GHashTable *client_table;
-} server_socket_context_t;
+#define MAX_ARRAY_LEN 65535
-static int __socket_writen(int fd, char *buf, int buf_size)
+int socket_send(int fd, char *buf, int len)
{
- int ret, writed = 0;
- while (buf_size)
- {
- ret = write(fd, buf+writed, buf_size);
- if (-1 == ret)
- {
- if (EINTR == errno)
- continue;
- else
- return ret;
- }
- writed += ret;
- buf_size -= ret;
- }
- return writed;
+ if (!buf || len <= 0) {
+ INFO("No data to send %p, %d", buf, len);
+ return -1;
+ }
+
+ int length = len;
+ int passed_len = 0;
+ int write_len = 0;
+
+ while (length > 0) {
+ passed_len = send(fd, (const void *)buf, length, MSG_NOSIGNAL);
+ if (passed_len == -1) {
+ if (errno == EINTR)
+ continue;
+ else if (errno == EAGAIN)
+ continue;
+ else if (errno == EWOULDBLOCK)
+ continue;
+ ERROR("send error [%d]", errno);
+ break;
+ } else if (passed_len == 0)
+ break;
+ length -= passed_len;
+ buf += passed_len;
+ }
+ write_len = len - length;
+
+ if (write_len != len) {
+ WARNING("WARNING: buf_size [%d] != write_len[%d]", len, write_len);
+ return -1;
+ }
+ VERBOSE("write_len [%d]", write_len);
+
+ return write_len;
}
-static int __socket_readn(int fd, char *buf, int buf_size)
+int socket_recv(int fd, void **buf, unsigned int len)
{
- int ret, read_size = 0;
-
- while (buf_size)
- {
- ret = read(fd, buf+read_size, buf_size);
- if (-1 == ret)
- {
- if (EINTR == errno)
- continue;
- else
- return ret;
- }
- read_size += ret;
- buf_size -= ret;
- }
- return read_size;
+ if (!buf) {
+ INFO("Buffer must not null");
+ return -1;
+ }
+
+ unsigned int length = len;
+ int read_len = 0;
+ int final_len = 0;
+ char *temp = *buf;
+
+ while (length > 0) {
+ read_len = read(fd, (void *)temp, length);
+ if (read_len < 0) {
+ if (errno == EINTR)
+ continue;
+ else if (errno == EAGAIN)
+ continue;
+ else if (errno == EWOULDBLOCK)
+ continue;
+ else if (errno == EPIPE) {
+ ERROR("connection closed : read err %d", errno, read_len, length);
+ free(*buf);
+ *buf = NULL;
+ return 0; /* connection closed */
+ }
+ ERROR("read err %d, read_len :%d, length : %d", errno, read_len, length);
+ final_len = read_len;
+ break;
+ } else if (read_len == 0)
+ break;
+
+ length -= read_len;
+ temp += read_len;
+ }
+
+ if (final_len == 0)
+ final_len = (len-length);
+
+ if (len != final_len) {
+ WARNING("WARNING: buf_size [%d] != read_len[%d]\n", read_len, final_len);
+ return -1;
+ }
+
+ ((char*)*buf)[len]= '\0';
+
+ return final_len;
}
-#define PIMS_IPC_PID_BUFFER_SIZE 20
-static gboolean __request_handler(GIOChannel *src, GIOCondition condition, gpointer data)
+int socket_send_data(int fd, char *buf, unsigned int len)
{
- server_socket_context_t *context = (server_socket_context_t*)data;
- int ret = -1;
- int fd = -1;
- int orig_fd = -1;
- char *pid = NULL;
- char buffer[PIMS_IPC_PID_BUFFER_SIZE] = "";
-
- fd = g_io_channel_unix_get_fd(src);
-
- if (G_IO_HUP & condition)
- {
- close(fd);
-
- if (g_hash_table_lookup_extended(context->client_table, GINT_TO_POINTER(fd),
- (gpointer*)&orig_fd, (gpointer*)&pid) == TRUE)
- {
- VERBOSE("found pid for %u = %s", fd, pid);
- context->callback((const char*)pid, context->user_data);
- g_hash_table_remove(context->client_table, (gconstpointer)fd);
- }
- else
- {
- VERBOSE("unable to find pid for %u", fd);
- }
-
- return FALSE;
- }
-
- memset(buffer, 0x00, PIMS_IPC_PID_BUFFER_SIZE);
- ret = read(fd, (char *)buffer, PIMS_IPC_PID_BUFFER_SIZE-1);
- if (ret <= 0)
- {
- ERROR("read error : %s", strerror(errno));
- close(fd);
-
- return FALSE;
- }
-
- VERBOSE("client fd = %u, pid = %s", fd, buffer);
- g_hash_table_insert(context->client_table, GINT_TO_POINTER(fd), g_strdup(buffer));
-
- pid_t mypid = getpid();
- ret = __socket_writen(fd, (char*)&mypid, sizeof(pid_t));
- if (ret != sizeof(pid_t))
- {
- ERROR("write error : %s", strerror(errno));
- close(fd);
- g_hash_table_remove(context->client_table, (gconstpointer)fd);
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean __socket_handler(GIOChannel *src, GIOCondition condition, gpointer data)
-{
- GIOChannel *channel;
- server_socket_context_t *context = (server_socket_context_t*)data;
- int client_sockfd = -1;
- int sockfd = context->sockfd;
- struct sockaddr_un clientaddr;
- socklen_t client_len = sizeof(clientaddr);
-
- client_sockfd = accept(sockfd, (struct sockaddr *)&clientaddr, &client_len);
- if (-1 == client_sockfd)
- {
- ERROR("accept error : %s", strerror(errno));
- return TRUE;
- }
-
- channel = g_io_channel_unix_new(client_sockfd);
- g_io_add_watch(channel, G_IO_IN|G_IO_HUP, __request_handler, data);
- g_io_channel_unref(channel);
-
- return TRUE;
+ int ret = 0;
+ int send_len = 0;
+ int remain_len = len;
+
+ if (len > MAX_ARRAY_LEN)
+ INFO("send long data : length(%d) ++++++++++++++++++++++++", len);
+
+ while (len > send_len) {
+ if (remain_len > MAX_ARRAY_LEN)
+ ret = socket_send(fd, (buf+send_len), MAX_ARRAY_LEN);
+ else
+ ret = socket_send(fd, (buf+send_len), remain_len);
+
+ if (ret < 0) {
+ ERROR("socket_send error");
+ break;
+ }
+ send_len += ret;
+ remain_len -= ret;
+ }
+
+ if (ret < 0) {
+ ERROR("socket_send error");
+ return -1;
+ }
+
+ return send_len;
}
-int _server_socket_init(const char *path, gid_t group, mode_t mode,
- server_socket_client_closed_cb callback, void *user_data)
+int write_command(int fd, const uint64_t cmd)
{
- int sockfd = -1;
- GIOChannel *gio = NULL;
-
- if (sd_listen_fds(1) == 1 && sd_is_socket_unix(SD_LISTEN_FDS_START, SOCK_STREAM, -1, path, 0) > 0)
- {
- DEBUG("using system daemon");
-
- sockfd = SD_LISTEN_FDS_START;
- }
- else
- {
- struct sockaddr_un addr;
- int ret = -1;
-
- DEBUG("using local socket");
+ // poll : Level Trigger
+ uint64_t clear_cmd = 0;
+ int ret = write(fd, &clear_cmd, sizeof(clear_cmd));
+ if (ret < 0)
+ ERROR("write fail (%d)", ret);
- unlink(path);
-
- bzero(&addr, sizeof(addr));
- addr.sun_family = AF_UNIX;
- snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path);
-
- sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
- if (-1 == sockfd)
- {
- ERROR("socket error : %s", strerror(errno));
- return -1;
- }
-
- ret = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
- if (-1 == ret)
- {
- ERROR("bind error : %s", strerror(errno));
- close(sockfd);
- return -1;
- }
-
- ret = chown(path, getuid(), group);
- ret = chmod(path, mode);
-
- ret = listen(sockfd, 30);
- if (-1 == ret)
- {
- ERROR("listen error : %s", strerror(errno));
- close(sockfd);
- return -1;
- }
- }
-
- gio = g_io_channel_unix_new(sockfd);
-
- server_socket_context_t *context = g_new0(server_socket_context_t, 1);
- context->sockfd = sockfd;
- context->callback = callback;
- context->user_data = user_data;
- context->client_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
- ASSERT(context->client_table);
-
- g_io_add_watch(gio, G_IO_IN, __socket_handler, (gpointer)context);
-
- return sockfd;
-}
-
-int _client_socket_init(const char *path, const char *pid)
-{
- int sockfd = -1;
- int ret = -1;
- struct sockaddr_un caddr = {0};
- pid_t server_pid = 0;
-
- ASSERT(path != NULL);
- ASSERT(pid != NULL);
- bzero(&caddr, sizeof(caddr));
- caddr.sun_family = AF_UNIX;
- snprintf(caddr.sun_path, sizeof(caddr.sun_path), "%s", path);
-
- sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
- if (-1 == sockfd)
- {
- ERROR("socket error : %s", strerror(errno));
- return -1;
- }
-
- ret = connect(sockfd, (struct sockaddr *)&caddr, sizeof(caddr));
- if (-1 == ret) {
- ERROR("connect error : %s", strerror(errno));
- close(sockfd);
- return -1;
- }
- ret = __socket_writen(sockfd, (char*)pid, strlen(pid) + 1);
- if (ret <= 0)
- {
- ERROR("write error : %s", strerror(errno));
- close(sockfd);
- return -1;
- }
- ret = __socket_readn(sockfd, (char*)&server_pid, sizeof(pid_t));
- if (ret != sizeof(pid_t))
- {
- ERROR("read error : %s", strerror(errno));
- close(sockfd);
- return -1;
- }
-
- return sockfd;
-}
-
-#else
-#include <pims-socket.h>
-
-int _server_socket_init(const char *path, gid_t group, mode_t mode,
- server_socket_client_closed_cb callback, void *user_data)
-{
- return 0;
+ return write(fd, &cmd, sizeof(cmd));
}
-int _client_socket_init(const char *path, const char *pid)
+int read_command(int fd, uint64_t *cmd)
{
- return 0;
+ uint64_t dummy;
+ int len = read(fd, &dummy, sizeof(dummy));
+ if (len == sizeof(dummy)) {
+ *cmd = dummy;
+ }
+ return len;
}
-#endif
#define __PIMS_SOCKET_H__
#include <unistd.h>
+#include <stdint.h>
#include <sys/stat.h>
#include <sys/types.h>
{
#endif
-typedef void (*server_socket_client_closed_cb)(const char *pid, void *user_data);
-int _server_socket_init(const char *path, gid_t group, mode_t mode,
- server_socket_client_closed_cb callback, void *user_data);
-int _client_socket_init(const char *path, const char *pid);
+int socket_send(int fd, char *buf, int len);
+int socket_recv(int fd, void **buf, unsigned int len);
+int socket_send_data(int fd, char *buf, unsigned int len);
+
+int write_command(int fd, const uint64_t cmd);
+int read_command(int fd, uint64_t *cmd);
#ifdef __cplusplus
}
+++ /dev/null
-CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-PROJECT(pims_ipc_test C)
-
-####################################################################
-# Basic configuration #
-####################################################################
-# Set ready to build
-SET(EXT_LIBS_DIRS "")
-SET(EXT_LIBS_DEFS "")
-SET(EXT_LIBS_LDFLAGS "")
-
-# Set external libraries
-SET(EXT_LIBS
- E_GLIB
-)
-
-FOREACH(flag ${EXT_LIBS})
- SET(EXT_LIBS_DIRS ${EXT_LIBS_DIRS} ${${flag}_INCLUDE_DIRS})
- SET(EXT_LIBS_DEFS ${EXT_LIBS_DEFS} ${${flag}_CFLAGS_OTHER})
- SET(EXT_LIBS_LDFLAGS ${EXT_LIBS_LDFLAGS} ${${flag}_LDFLAGS})
-ENDFOREACH(flag)
-
-####################################################################
-# Build this project #
-####################################################################
-
-# Set source
-SET(SRCS
- ${CMAKE_CURRENT_SOURCE_DIR}/test.c
-)
-
-INCLUDE_DIRECTORIES(
- ${CMAKE_SOURCE_DIR}/include
- ${EXT_LIBS_DIRS}
-)
-
-ADD_DEFINITIONS(
- ${EXT_LIBS_DEFS}
-)
-
-ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS})
-TARGET_LINK_LIBRARIES(${PROJECT_NAME} pims-ipc ${EXT_LIBS_LDFLAGS})
-INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIB_INSTALL_DIR})
-
+++ /dev/null
-/*
- * PIMS IPC
- *
- * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#define NAME "dom_sock_test"
-
-#define REPEAT_COUNT 100
-//#define BUFFER_SIZE 1024*1024
-#define BUFFER_SIZE 1024
-
-#define PLUS_TIME(a, b, c) do {\
- a.tv_sec = b.tv_sec + c.tv_sec;\
- a.tv_usec = b.tv_usec + c.tv_usec;\
- if (a.tv_usec >= 1000000) {\
- a.tv_sec++;\
- a.tv_usec -= 1000000;\
- }\
-} while (0)
-
-#define MINUS_TIME(a, b, c) do {\
- a.tv_sec = b.tv_sec - c.tv_sec;\
- a.tv_usec = b.tv_usec - c.tv_usec;\
- if (a.tv_usec < 0) {\
- a.tv_sec--;\
- a.tv_usec += 1000000;\
- }\
-} while (0)
-
-
-static char buffer[BUFFER_SIZE+1] = {0,};
-
-void server_main()
-{
- int sock, msgsock, rval;
- struct sockaddr_un server;
-
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sock < 0) {
- perror("opening stream socket");
- exit(1);
- }
-
- server.sun_family = AF_UNIX;
- strcpy(server.sun_path, NAME);
- if (bind(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un))) {
- perror("binding stream socket");
- exit(1);
- }
- printf("Socket has name %s\n", server.sun_path);
- listen(sock, 5);
- for (;;) {
- msgsock = accept(sock, 0, 0);
- if (msgsock == -1)
- perror("accept");
- else do {
- if ((rval = read(msgsock, buffer, BUFFER_SIZE)) < 0)
- perror("reading stream message");
- else if (rval == 0)
- printf("Ending connection\n");
- else
- {
- if ((rval = write(msgsock, buffer, BUFFER_SIZE)) < 0)
- perror("writing stream message");
-
- }
- } while (rval > 0);
- close(msgsock);
- }
- close(sock);
- unlink(NAME);
-}
-
-void client_main()
-{
- int i;
- int sock;
- struct sockaddr_un server;
- struct timeval start_tv = {0, 0};
- struct timeval end_tv = {0, 0};
- struct timeval diff_tv = {0, 0};
- struct timeval prev_sum_tv = {0, 0};
- struct timeval sum_tv = {0, 0};
- int count = 0;
-
- sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sock < 0) {
- perror("opening stream socket");
- exit(1);
- }
- server.sun_family = AF_UNIX;
- strcpy(server.sun_path, NAME);
-
- for (i = 0; i < BUFFER_SIZE; i++)
- buffer[i] = 'a';
- buffer[i] = 0;
-
- if (connect(sock, (struct sockaddr *) &server, sizeof(struct sockaddr_un)) < 0) {
- close(sock);
- perror("connecting stream socket");
- exit(1);
- }
- for (i = 0; i < REPEAT_COUNT; i++)
- {
-
- gettimeofday(&start_tv, NULL);
- if (write(sock, buffer, BUFFER_SIZE) < 0)
- perror("writing on stream socket");
- if (read(sock, buffer, BUFFER_SIZE) < 0)
- perror("read on stream socket");
- gettimeofday(&end_tv, NULL);
- MINUS_TIME(diff_tv, end_tv, start_tv);
- PLUS_TIME(sum_tv, diff_tv, prev_sum_tv);
- prev_sum_tv = sum_tv;
- count++;
- printf("start[%lu:%lu] end[%lu:%lu] diff[%lu:%lu]\n",
- start_tv.tv_sec, start_tv.tv_usec,
- end_tv.tv_sec, end_tv.tv_usec,
- diff_tv.tv_sec, diff_tv.tv_usec);
-
- }
- if (i == REPEAT_COUNT)
- {
- printf("sum[%lu:%lu] count[%d]\n",
- sum_tv.tv_sec, sum_tv.tv_usec, count);
- printf("avg[%lu:%lu]\n",
- sum_tv.tv_sec / count, (sum_tv.tv_sec % count * 1000000 + sum_tv.tv_usec) / count);
- }
-
- close(sock);
-}
-
-int main(int argc, char *argv[])
-{
- if (argc != 2)
- {
- printf("Usage: %s client|server\n", argv[0]);
- return -1;
- }
- if (strcmp(argv[1], "client") == 0)
- {
- printf("client mode..\n");
- client_main();
- }
- else if (strcmp(argv[1], "server") == 0)
- {
- printf("server mode..\n");
- server_main();
- }
- else
- {
- printf("Usage: %s client|server\n", argv[0]);
- return -1;
- }
- return 0;
-}
-
-
+++ /dev/null
-/*
- * PIMS IPC
- *
- * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <glib.h>
-#include <pims-ipc.h>
-#include <pims-ipc-svc.h>
-#include <pims-ipc-data.h>
-
-#define THREAD_COUNT 1
-#define REPEAT_COUNT 100
-#define BUFFER_SIZE 1024
-#define PLUS_TIME(a, b, c) do {\
- a.tv_sec = b.tv_sec + c.tv_sec;\
- a.tv_usec = b.tv_usec + c.tv_usec;\
- if (a.tv_usec >= 1000000) {\
- a.tv_sec++;\
- a.tv_usec -= 1000000;\
- }\
-} while (0)
-
-#define MINUS_TIME(a, b, c) do {\
- a.tv_sec = b.tv_sec - c.tv_sec;\
- a.tv_usec = b.tv_usec - c.tv_usec;\
- if (a.tv_usec < 0) {\
- a.tv_sec--;\
- a.tv_usec += 1000000;\
- }\
-} while (0)
-
-typedef struct {
- int thread_count;
- int repeat_count;
- int message_size;
- pims_ipc_h ipc;
-} test_arg_t;
-
-static gboolean __is_async = FALSE;
-static gboolean __is_publish = FALSE;
-
-void test_function(pims_ipc_h ipc, pims_ipc_data_h indata, pims_ipc_data_h *outdata, void *userdata)
-{
- unsigned int size = 0;
- char *str = NULL;
-
- if (indata)
- {
- str = (char*)pims_ipc_data_get(indata, &size);
- if (!str)
- {
- printf("pims_ipc_data_get error\n");
- return;
- }
-#if 0
- str = (char*)pims_ipc_data_get(indata, &size);
- if (!str)
- {
- printf("pims_ipc_data_get error\n");
- return;
- }
- printf("%s\n", str);
- str = (char*)pims_ipc_data_get(indata, &size);
- if (!str)
- {
- printf("pims_ipc_data_get error\n");
- return;
- }
- printf("%s\n", str);
-#endif
- }
-
- if (str && outdata)
- {
- *outdata = pims_ipc_data_create(0);
- if (!*outdata)
- {
- printf("pims_ipc_data_create error\n");
- return;
- }
- if (pims_ipc_data_put(*outdata, str, strlen(str) + 1) != 0)
- {
- printf("pims_ipc_data_put error\n");
- pims_ipc_data_destroy(*outdata);
- *outdata = NULL;
- return;
- }
-#if 0
- if (pims_ipc_data_put(*outdata, "welcome", strlen("welcome") + 1) != 0)
- {
- printf("pims_ipc_data_put error\n");
- pims_ipc_data_destroy(*outdata);
- *outdata = NULL;
- return;
- }
- if (pims_ipc_data_put(*outdata, "to the jungle", strlen("to the jungle") + 1) != 0)
- {
- printf("pims_ipc_data_put error\n");
- pims_ipc_data_destroy(*outdata);
- *outdata = NULL;
- return;
- }
-#endif
- }
-}
-
-static gboolean publish_callback(gpointer data)
-{
- pims_ipc_data_h indata = NULL;
-
- indata = pims_ipc_data_create(0);
- if (!indata)
- {
- printf("pims_ipc_data_create error\n");
- return false;
- }
- if (pims_ipc_data_put(indata, "publish test", strlen("publish test") + 1) != 0)
- {
- printf("pims_ipc_data_put error\n");
- return false;
- }
- if (pims_ipc_svc_publish("test_module", "publish", indata) != 0)
- {
- printf("pims_ipc_svc_publish error\n");
- return false;
- }
-
- if (indata)
- pims_ipc_data_destroy(indata);
-
- return true;
-}
-
-int server_main()
-{
-
- pims_ipc_svc_init("pims-ipc-test", getuid(), 0660);
-
- if (pims_ipc_svc_register("test_module", "test_function", test_function, NULL) != 0)
- {
- printf("pims_ipc_svc_register error\n");
- return -1;
- }
-
- if (__is_publish)
- {
- pims_ipc_svc_init_for_publish("pims-ipc-pub-test", getuid(), 0660);
- g_timeout_add_seconds(3, publish_callback, NULL);
- }
-
- pims_ipc_svc_run_main_loop(NULL);
-
- pims_ipc_svc_deinit();
-
- return 0;
-}
-
-static gboolean call_async_idler_callback(gpointer data);
-
-static void call_async_callback(pims_ipc_h ipc, pims_ipc_data_h data_out, void *userdata)
-{
- unsigned int size = 0;
- char *str = NULL;
-
- printf("(%x) call_async_callback(%p)", (unsigned int)pthread_self(), ipc);
- if (data_out)
- {
- str = (char*)pims_ipc_data_get(data_out, &size);
- if (!str)
- {
- printf("pims_ipc_data_get error\n");
- }
- else
- {
- printf("pims_ipc_data_get(%s) success\n", str);
- }
- }
-
- sleep(1);
-
- pims_ipc_data_h indata = NULL;
- pims_ipc_data_h outdata = NULL;
-
- indata = pims_ipc_data_create(0);
- if (!indata)
- {
- printf("pims_ipc_data_create error\n");
- return;
- }
- if (pims_ipc_data_put(indata, "hello world", strlen("hello world") + 1) != 0)
- {
- printf("pims_ipc_data_put error\n");
- return;
- }
-
- if (pims_ipc_call(ipc, "test_module", "test_function", indata, &outdata) != 0)
- {
- printf("pims_ipc_call error\n");
- return;
- }
-
- if (indata)
- pims_ipc_data_destroy(indata);
- if (outdata)
- pims_ipc_data_destroy(outdata);
-
- sleep(1);
-
- call_async_idler_callback(ipc);
-}
-
-static gboolean call_async_idler_callback(gpointer data)
-{
- pims_ipc_data_h indata = NULL;
- pims_ipc_data_h outdata = NULL;
- pims_ipc_h ipc = data;
- bool ret = false;
-
- indata = pims_ipc_data_create(0);
- if (!indata)
- {
- printf("pims_ipc_data_create error\n");
- return FALSE;
- }
- if (pims_ipc_data_put(indata, "hello world", strlen("hello world") + 1) != 0)
- {
- printf("pims_ipc_data_put error\n");
- return FALSE;
- }
-
- printf("(%x) call_async_idler_callback(%p)\n", (unsigned int)pthread_self(), ipc);
- ret = pims_ipc_is_call_in_progress(ipc);
- printf("(%x) before async call : pims_ipc_is_call_in_progress(%p) = %d\n", (unsigned int)pthread_self(), ipc, ret);
- if (pims_ipc_call_async(ipc, "test_module", "test_function", indata, call_async_callback, NULL) != 0)
- {
- printf("pims_ipc_call_async error\n");
- return FALSE;
- }
- ret = pims_ipc_is_call_in_progress(ipc);
- printf("(%x) after async call : pims_ipc_is_call_in_progress(%p) = %d\n", (unsigned int)pthread_self(), ipc, ret);
-
- if (pims_ipc_call(ipc, "test_module", "test_function", indata, &outdata) != 0)
- {
- printf("pims_ipc_call error during async-call\n");
- return FALSE;
- }
- if (indata)
- pims_ipc_data_destroy(indata);
- if (outdata)
- pims_ipc_data_destroy(outdata);
-
- return FALSE;
-}
-
-int client_main(pims_ipc_h ipc, int repeat_count, int message_size)
-{
- pims_ipc_data_h indata = NULL;
- pims_ipc_data_h outdata = NULL;
- int retval = -1;
- unsigned int size = 0;
- char *str = NULL;
- int i = 0;
- struct timeval start_tv = {0, 0};
- struct timeval end_tv = {0, 0};
- struct timeval diff_tv = {0, 0};
- struct timeval prev_sum_tv = {0, 0};
- struct timeval sum_tv = {0, 0};
- int count = 0;
-
- char *buffer = g_malloc0(message_size + 1);
-
- for (i = 0; i < message_size; i++)
- buffer[i] = 'a';
- buffer[i] = 0;
-
- for (i = 0; i < repeat_count; i++)
- {
- gettimeofday(&start_tv, NULL);
- indata = pims_ipc_data_create(0);
- if (!indata)
- {
- printf("pims_ipc_data_create error\n");
- break;
- }
- if (pims_ipc_data_put(indata, buffer, strlen(buffer) + 1) != 0)
- {
- printf("pims_ipc_data_put error\n");
- break;
- }
-#if 0
- if (pims_ipc_data_put(indata, "hellow", strlen("hellow") + 1) != 0)
- {
- printf("pims_ipc_data_put error\n");
- break;
- }
- if (pims_ipc_data_put(indata, "world", strlen("world") + 1) != 0)
- {
- printf("pims_ipc_data_put error\n");
- break;
- }
-#endif
- if (pims_ipc_call(ipc, "test_module", "test_function", indata, &outdata) != 0)
- {
- printf("pims_ipc_call error\n");
- break;
- }
- pims_ipc_data_destroy(indata);
- indata = NULL;
- if (outdata)
- {
- str = (char*)pims_ipc_data_get(outdata, &size);
- if (!str)
- {
- printf("pims_ipc_data_get error\n");
- break;
- }
-#if 0
- str = (char*)pims_ipc_data_get(outdata, &size);
- if (!str)
- {
- printf("pims_ipc_data_get error\n");
- break;
- }
- printf("%s\n", str);
- str = (char*)pims_ipc_data_get(outdata, &size);
- if (!str)
- {
- printf("pims_ipc_data_get error\n");
- break;
- }
- printf("%s\n", str);
-#endif
-
- pims_ipc_data_destroy(outdata);
- outdata = NULL;
- }
- gettimeofday(&end_tv, NULL);
- MINUS_TIME(diff_tv, end_tv, start_tv);
- PLUS_TIME(sum_tv, diff_tv, prev_sum_tv);
- prev_sum_tv = sum_tv;
- count++;
- printf("(%x) start[%lu:%lu] end[%lu:%lu] diff[%lu:%lu]\n",
- (unsigned int)pthread_self(),
- start_tv.tv_sec, start_tv.tv_usec,
- end_tv.tv_sec, end_tv.tv_usec,
- diff_tv.tv_sec, diff_tv.tv_usec);
- }
-
- if (i == repeat_count)
- {
- printf("(%x) sum[%lu:%lu] count[%d]\n",
- (unsigned int)pthread_self(),
- sum_tv.tv_sec, sum_tv.tv_usec, count);
- printf("(%x) avg[%lu:%lu]\n",
- (unsigned int)pthread_self(),
- sum_tv.tv_sec / count, (sum_tv.tv_sec % count * 1000000 + sum_tv.tv_usec) / count);
- retval = 0;
- }
-
- if (indata)
- pims_ipc_data_destroy(indata);
- if (outdata)
- pims_ipc_data_destroy(outdata);
-
- if (__is_async)
- g_idle_add(call_async_idler_callback, ipc);
-
- return retval;
-}
-
-static void* __worker_task(void *arg)
-{
- test_arg_t *_arg = arg;
- printf("(%x) worker %p, %d, %d\n", (unsigned int)pthread_self(), _arg->ipc, _arg->repeat_count, _arg->message_size);
- client_main(_arg->ipc, _arg->repeat_count, _arg->message_size);
- printf("worker task has been done\n");
- return NULL;
-}
-
-static gboolean __launch_worker(gpointer data)
-{
- test_arg_t *_arg = data;
- int i = 0;
- GThread **worker_threads = NULL;
- gboolean joinable = FALSE;
-
- worker_threads = g_new0(GThread*, _arg->thread_count);
- if (!__is_async && !__is_publish)
- joinable = TRUE;
-
- for (i = 0; i < _arg->thread_count; i++)
- {
- pims_ipc_h ipc = NULL;
- test_arg_t *arg = g_new0(test_arg_t, 1);
- arg->repeat_count = _arg->repeat_count;
- arg->message_size = _arg->message_size;
- ipc = pims_ipc_create("pims-ipc-test");
- if (!ipc)
- {
- printf("pims_ipc_create error\n");
- return -1;
- }
- arg->ipc = ipc;
-
- worker_threads[i] = g_thread_create(__worker_task, (void*)arg, joinable, NULL);
- }
-
- if (!__is_async && !__is_publish)
- {
- for (i = 0; i < _arg->thread_count; i++)
- {
- g_thread_join(worker_threads[i]);
- }
- }
-
- g_free(worker_threads);
-
- return FALSE;
-}
-
-static void subscribe_callback(pims_ipc_h ipc, pims_ipc_data_h data, void *userdata)
-{
- unsigned int size = 0;
- char *str = NULL;
-
- printf("(%x) subscribe_callback(%p)", (unsigned int)pthread_self(), ipc);
- if (data)
- {
- str = (char*)pims_ipc_data_get(data, &size);
- if (!str)
- {
- printf("pims_ipc_data_get error\n");
- }
- else
- {
- printf("pims_ipc_data_get(%s) success\n", str);
- }
- }
-}
-
-static void __print_usage(char *prog)
-{
- printf("Usage: %s [-r <repeat count> -s <message size> -t <thread count> -a] client|server \n", prog);
-}
-
-int main(int argc, char *argv[])
-{
- int repeat_count = REPEAT_COUNT;
- int message_size = BUFFER_SIZE;
- int thread_count = THREAD_COUNT;
- int c = 0;
- test_arg_t arg;
-
- opterr = 0;
- optind = 0;
-
- g_thread_init(NULL);
-
- while ((c = getopt(argc, argv, "r:s:t:ap")) != -1)
- {
- switch (c)
- {
- case 'r':
- repeat_count = atoi(optarg);
- break;
- case 's':
- message_size = atoi(optarg);
- break;
- case 't':
- thread_count = atoi(optarg);
- break;
- case 'a':
- __is_async = TRUE;
- break;
- case 'p':
- __is_publish = TRUE;
- break;
- case '?':
- __print_usage(argv[0]);
- return -1;
- }
-
- }
-
- if (argc - optind != 1)
- {
- __print_usage(argv[0]);
- return -1;
- }
-
- if (strcmp(argv[optind], "client") == 0)
- {
- // async call
- GMainLoop* main_loop = g_main_loop_new(NULL, FALSE);
-
- printf("client mode.. with %d threads\n", thread_count);
-
- if (__is_publish)
- {
- pims_ipc_h ipc = NULL;
- ipc = pims_ipc_create_for_subscribe("pims-ipc-pub-test");
- if (!ipc)
- {
- printf("pims_ipc_create_for_subscribe error\n");
- return -1;
- }
- pims_ipc_destroy_for_subscribe(ipc);
- ipc = pims_ipc_create_for_subscribe("pims-ipc-pub-test");
- if (!ipc)
- {
- printf("pims_ipc_create_for_subscribe error\n");
- return -1;
- }
- if (pims_ipc_subscribe(ipc, "test_module", "publish", subscribe_callback, NULL) != 0)
- {
- printf("pims_ipc_subscribe error\n");
- return -1;
- }
- if (pims_ipc_unsubscribe(ipc, "test_module", "publish") != 0)
- {
- printf("pims_ipc_unsubscribe error\n");
- return -1;
- }
- if (pims_ipc_subscribe(ipc, "test_module", "publish", subscribe_callback, NULL) != 0)
- {
- printf("pims_ipc_subscribe error\n");
- return -1;
- }
- }
-
- if (thread_count <= 1)
- {
- pims_ipc_h ipc = NULL;
- ipc = pims_ipc_create("pims-ipc-test");
- if (!ipc)
- {
- printf("pims_ipc_create error\n");
- return -1;
- }
-
- client_main(ipc, repeat_count, message_size);
- }
- else
- {
- arg.message_size = message_size;
- arg.repeat_count = repeat_count;
- arg.thread_count = thread_count;
- if (__is_async || __is_publish)
- g_idle_add(__launch_worker, &arg);
- else
- __launch_worker(&arg);
- }
-
- if (__is_async || __is_publish)
- g_main_loop_run(main_loop);
- }
- else if (strcmp(argv[optind], "server") == 0)
- {
- printf("server mode..\n");
- server_main();
- }
- else
- {
- __print_usage(argv[0]);
- return -1;
- }
- return 0;
-}