axl_bool __turbulence_loop_read_first (TurbulenceLoop * loop) { TurbulenceLoopDescriptor * loop_descriptor; loop_descriptor = vortex_async_queue_pop (loop->queue); /* check item received: if null received terminate loop */ if (PTR_TO_INT (loop_descriptor) == -4) return axl_false; /* register loop_descriptor on the list */ axl_list_append (loop->list, loop_descriptor); return axl_true; }
/** * @brief Allows to get a list of connections registered on the * connection manager, matching the providing role and then filtered * by the provided filter string. * * @param ctx The context where the operation will take place. * * @param role Connection role to select connections. Use -1 to select * all connections registered on the manager, no matter its role. * * @param filter Optional filter expresion to resulting connection * list. It can be NULL. * * @return A newly allocated connection list having on each position a * reference to a MyQttConn object. The caller must finish the * list with axl_list_free to free resources. The function returns NULL if it fails. */ axlList * myqttd_conn_mgr_conn_list (MyQttdCtx * ctx, MyQttPeerRole role, const char * filter) { axlList * result; MyQttConn * conn; axlHashCursor * cursor; MyQttdConnMgrState * state; v_return_val_if_fail (ctx, NULL); /* lock and send */ myqtt_mutex_lock (&ctx->conn_mgr_mutex); /* create the cursor */ cursor = axl_hash_cursor_new (ctx->conn_mgr_hash); result = axl_list_new (axl_list_always_return_1, myqttd_conn_mgr_conn_list_free_item); msg ("connections registered: %d..", axl_hash_items (ctx->conn_mgr_hash)); while (axl_hash_cursor_has_item (cursor)) { /* get data */ state = axl_hash_cursor_get_value (cursor); conn = state->conn; /* check connection role to add it to the result list */ msg ("Checking connection role %d == %d", myqtt_conn_get_role (conn), role); if ((role == -1) || myqtt_conn_get_role (conn) == role) { /* update reference and add the connection */ myqtt_conn_ref (conn, "conn-mgr-list"); axl_list_append (result, conn); } /* end if */ /* next cursor */ axl_hash_cursor_next (cursor); } /* unlock */ myqtt_mutex_unlock (&ctx->conn_mgr_mutex); /* free cursor */ axl_hash_cursor_free (cursor); /* return list */ return result; }
axl_bool __turbulence_loop_read_pending (TurbulenceLoop * loop) { TurbulenceLoopDescriptor * loop_descriptor, * aux; while (axl_true) { /* check if there are no pending items */ if (vortex_async_queue_items (loop->queue) == 0) return axl_true; /* get descriptor */ loop_descriptor = vortex_async_queue_pop (loop->queue); /* check item received: if null received terminate loop */ if (PTR_TO_INT (loop_descriptor) == -4) return axl_false; /* support for removing loop descriptor */ if (loop_descriptor->remove) { /* reset cursor to the first position */ axl_list_cursor_first (loop->cursor); while (axl_list_cursor_has_item (loop->cursor)) { /* get current descriptor */ aux = axl_list_cursor_get (loop->cursor); if (aux && aux->descriptor == loop_descriptor->descriptor) { /* element found, remove item */ axl_list_cursor_remove (loop->cursor); break; } /* end if */ /* next cursor */ axl_list_cursor_next (loop->cursor); } /* end if */ /* notify caller if he is waiting */ if (loop_descriptor->queue_reply) vortex_async_queue_push (loop_descriptor->queue_reply, INT_TO_PTR (axl_true)); axl_free (loop_descriptor); continue; } /* end if */ /* register loop_descriptor on the list */ axl_list_append (loop->list, loop_descriptor); } /* end if */ return axl_true; }
/** * @brief Queues new data inside the given queue. * * push data at the queue's tail. * * @param queue the queue to use. * @param data user defined data to queue. * * @return axl_true if the data was queue, axl_false if not **/ axl_bool vortex_queue_push (VortexQueue * queue, axlPointer data) { /* check parameter */ if (queue == NULL || data == NULL) return axl_false; vortex_mutex_lock (&queue->mutex); /* place the data into the last position. The head queue is * the first element to be poped, and the tail is where new * data is placed. */ axl_list_append (queue->queue, data); vortex_mutex_unlock (&queue->mutex); return axl_true; }
enum jal_status jaln_process_init(VortexFrame *frame, struct jaln_init_info **info_out) { if (!frame || !info_out || *info_out) { return JAL_E_INVAL; } enum jal_status ret = JAL_E_INVAL; struct jaln_init_info *info = jaln_init_info_create(); if (!jaln_check_content_type_and_txfr_encoding_are_valid(frame)) { goto err_out; } const char *msg = VORTEX_FRAME_GET_MIME_HEADER(frame, JALN_HDRS_MESSAGE); if (!msg) { goto err_out; } if (0 != strcasecmp(msg, JALN_MSG_INIT)) { goto err_out; } const char *role = VORTEX_FRAME_GET_MIME_HEADER(frame, JALN_HDRS_MODE); if (!role) { goto err_out; } if (0 == strcasecmp(role, JALN_MSG_SUBSCRIBE_LIVE)) { info->role = JALN_ROLE_SUBSCRIBER; info->mode = JALN_LIVE_MODE; } else if (0 ==strcasecmp(role, JALN_MSG_SUBSCRIBE_ARCHIVE)) { info->role = JALN_ROLE_SUBSCRIBER; info->mode = JALN_ARCHIVE_MODE; } else if (0 == strcasecmp(role, JALN_MSG_PUBLISH_LIVE)) { info->role = JALN_ROLE_PUBLISHER; info->mode = JALN_LIVE_MODE; } else if (0 == strcasecmp(role, JALN_MSG_PUBLISH_ARCHIVE)) { info->role = JALN_ROLE_PUBLISHER; info->mode = JALN_ARCHIVE_MODE; } else { goto err_out; } const char *type = VORTEX_FRAME_GET_MIME_HEADER(frame, JALN_HDRS_DATA_CLASS); if (!type) { goto err_out; } if (0 == strcasecmp(type, JALN_STR_JOURNAL)) { info->type = JALN_RTYPE_JOURNAL; } else if (0 == strcasecmp(type, JALN_STR_AUDIT)) { info->type = JALN_RTYPE_AUDIT; } else if (0 == strcasecmp(type, JALN_STR_LOG)) { info->type = JALN_RTYPE_LOG; } else { goto err_out; } const char *agent = VORTEX_FRAME_GET_MIME_HEADER(frame, JALN_HDRS_AGENT); if (agent) { info->peer_agent = jal_strdup(agent); } char *cpy = NULL; const char *accept_dgst = VORTEX_FRAME_GET_MIME_HEADER(frame, JALN_HDRS_ACCEPT_DIGEST); if (accept_dgst) { cpy = jal_strdup(accept_dgst); char *cookie = NULL; char *token = NULL; for (token = strtok_r(cpy, ",", &cookie); token != NULL; token = strtok_r(NULL, ",", &cookie)) { axl_stream_trim(token); if (0 == strlen(token)) { goto err_out; } axl_list_append(info->digest_algs, jal_strdup(token)); } free(cpy); cpy = NULL; } else { axl_list_append(info->digest_algs, jal_strdup(JALN_DGST_SHA256)); } const char *accept_enc = VORTEX_FRAME_GET_MIME_HEADER(frame, JALN_HDRS_ACCEPT_ENCODING); if (accept_enc) { cpy = jal_strdup(accept_enc); char *cookie = NULL; char *token = NULL; for (token = strtok_r(cpy, ",", &cookie); token != NULL; token = strtok_r(NULL, ",", &cookie)) { axl_stream_trim(token); if (0 == strlen(token)) { goto err_out; } axl_list_append(info->encodings, jal_strdup(token)); } free(cpy); cpy = NULL; } else { axl_list_append(info->encodings, jal_strdup(JALN_ENC_XML)); } ret = JAL_OK; *info_out = info; goto out; err_out: jaln_init_info_destroy(&info); out: return ret; }
/** * @internal * * This helper function dispatch the work to the right handler **/ axlPointer __valvula_thread_pool_dispatcher (ValvulaThreadPoolStarter * _data) { /* get current context */ ValvulaThreadPoolTask * task; ValvulaThread * thread = _data->thread; ValvulaThreadPool * pool = _data->pool; ValvulaCtx * ctx = pool->ctx; ValvulaAsyncQueue * queue = _data->queue; /* local pointers to release soon data object */ ValvulaThreadFunc func; axlPointer data; axl_free (_data); valvula_log (VALVULA_LEVEL_DEBUG, "thread from pool started"); /* get a reference to the queue, waiting for the next work */ while (axl_true) { /* get next task to process: precision=100ms */ task = valvula_async_queue_timedpop (queue, 100000); if (task == NULL) { /* call to process events */ __valvula_thread_pool_process_events (ctx, pool); /* do automatic reasize */ __valvula_thread_pool_automatic_resize (ctx); continue; } if (PTR_TO_INT (task) == 3) { /* collect thread data terminated */ valvula_mutex_lock (&(ctx->thread_pool->stopped_mutex)); axl_list_remove_first (pool->stopped); valvula_mutex_unlock (&(ctx->thread_pool->stopped_mutex)); continue; } /* check to stop current thread because pool was reduced */ if (PTR_TO_INT (task) == 2) { valvula_log (VALVULA_LEVEL_DEBUG, "--> thread from pool stoping, found thread stop beacon"); /* do not lock because this is already done by * valvula_thread_pool_remove .. */ valvula_mutex_lock (&(ctx->thread_pool->stopped_mutex)); /* remove thread from the pool */ valvula_mutex_lock (&pool->mutex); axl_list_unlink_ptr (pool->threads, thread); valvula_mutex_unlock (&pool->mutex); axl_list_append (pool->stopped, thread); valvula_mutex_unlock (&(ctx->thread_pool->stopped_mutex)); valvula_async_queue_push (queue, INT_TO_PTR (3)); /* unref the queue and return */ valvula_async_queue_unref (queue); /* call to cleanup thread if defined */ if (ctx->thread_pool_cleanup) ctx->thread_pool_cleanup (ctx); /* unref ctx */ valvula_ctx_unref2 (&ctx, "end pool dispatcher"); return NULL; } /* end if */ /* check stop in progress signal */ if ((PTR_TO_INT (task) == 1) && ctx->thread_pool_being_stopped) { valvula_log (VALVULA_LEVEL_DEBUG, "--> thread from pool stoping, found finish beacon"); /* unref the queue and return */ valvula_async_queue_unref (queue); /* call to cleanup thread if defined */ if (ctx->thread_pool_cleanup) ctx->thread_pool_cleanup (ctx); valvula_ctx_unref2 (&ctx, "end pool dispatcher"); return NULL; } /* end if */ valvula_log (VALVULA_LEVEL_DEBUG, "--> thread from pool processing new job"); /* grab references to release before call */ func = task->func; data = task->data; axl_free (task); /* do automatic reasize (preemtive) */ if (ctx && ctx->thread_pool && ctx->thread_pool->preemtive) __valvula_thread_pool_automatic_resize (ctx); /* at this point we already are executing inside a thread */ if (! ctx->thread_pool_being_stopped && ! ctx->valvula_exit) func (data); /* call to process events after finishing tasks */ __valvula_thread_pool_process_events (ctx, pool); /* do automatic reasize */ if (ctx && ctx->thread_pool && ! ctx->thread_pool->preemtive) __valvula_thread_pool_automatic_resize (ctx); valvula_log (VALVULA_LEVEL_DEBUG, "--> thread from pool waiting for jobs"); } /* end if */ /* That's all! */ valvula_ctx_unref2 (&ctx, "end pool dispatcher"); return NULL; }