/**
 * [ReactorThread] dispatch request to worker
 */
static int swFactoryProcess_dispatch(swFactory *factory, swDispatchData *task)
{
    uint32_t schedule_key;
    uint32_t send_len = sizeof(task->data.info) + task->data.info.len;
    uint16_t target_worker_id;
    swServer *serv = SwooleG.serv;

    if (task->target_worker_id < 0)
    {
        schedule_key = task->data.info.fd;
#ifndef SW_USE_RINGBUFFER
        if (SwooleTG.factory_lock_target)
        {
            if (SwooleTG.factory_target_worker < 0)
            {
                target_worker_id = swServer_worker_schedule(serv, schedule_key);
                SwooleTG.factory_target_worker = target_worker_id;
            }
            else
            {
                target_worker_id = SwooleTG.factory_target_worker;
            }
        }
        else
#endif
        {
            target_worker_id = swServer_worker_schedule(serv, schedule_key);
        }
    }
    else
    {
        target_worker_id = task->target_worker_id;
    }

    if (swEventData_is_stream(task->data.info.type))
    {
        swConnection *conn = swServer_connection_get(serv, task->data.info.fd);
        if (conn == NULL || conn->active == 0)
        {
            swWarn("dispatch[type=%d] failed, connection#%d is not active.", task->data.info.type, task->data.info.fd);
            return SW_ERR;
        }
        //server active close, discard data.
        if (conn->closed)
        {
            if (!(task->data.info.type == SW_EVENT_CLOSE && conn->close_force))
            {
                swWarn("dispatch[type=%d] failed, connection#%d[session_id=%d] is closed by server.",
                        task->data.info.type, task->data.info.fd, conn->session_id);
                return SW_OK;
            }
        }
        //converted fd to session_id
        task->data.info.fd = conn->session_id;
        task->data.info.from_fd = conn->from_fd;
    }

    return swReactorThread_send2worker((void *) &(task->data), send_len, target_worker_id);
}
Exemple #2
0
/**
 * [ReactorThread] dispatch request to worker
 */
int swFactoryProcess_dispatch(swFactory *factory, swDispatchData *task)
{
    uint32_t schedule_key;
    uint32_t send_len = sizeof(task->data.info) + task->data.info.len;
    uint16_t target_worker_id;
    swServer *serv = SwooleG.serv;

    if (task->target_worker_id < 0)
    {
        //udp use remote port
        if (task->data.info.type == SW_EVENT_UDP || task->data.info.type == SW_EVENT_UDP6
                || task->data.info.type == SW_EVENT_UNIX_DGRAM)
        {
            schedule_key = task->data.info.from_id;
        }
        else
        {
            schedule_key = task->data.info.fd;
        }

#ifndef SW_USE_RINGBUFFER
        if (SwooleTG.factory_lock_target)
        {
            if (SwooleTG.factory_target_worker < 0)
            {
                target_worker_id = swServer_worker_schedule(serv, schedule_key);
                SwooleTG.factory_target_worker = target_worker_id;
            }
            else
            {
                target_worker_id = SwooleTG.factory_target_worker;
            }
        }
        else
#endif
        {
            target_worker_id = swServer_worker_schedule(serv, schedule_key);
        }
    }
    else
    {
        target_worker_id = task->target_worker_id;
    }

    if (SwooleTG.type == SW_THREAD_REACTOR)
    {
        return swReactorThread_send2worker((void *) &(task->data), send_len, target_worker_id);
    }
    else
    {
        swTrace("dispatch to worker#%d", target_worker_id);
        return swServer_send2worker_blocking(serv, (void *) &(task->data), send_len, target_worker_id);
    }
}
Exemple #3
0
int swConnection_send_in_buffer(swConnection *conn)
{
    swDispatchData task;
    swFactory *factory = SwooleG.factory;

    task.data.info.fd = conn->fd;
    task.data.info.from_id = conn->from_id;

    swBuffer *buffer = conn->in_buffer;
    swBuffer_trunk *trunk = swBuffer_get_trunk(buffer);

#ifdef SW_USE_RINGBUFFER

    swServer *serv = SwooleG.serv;
    uint16_t target_worker_id = swServer_worker_schedule(serv, conn->fd);
    swWorker *worker = swServer_get_worker(serv, target_worker_id);
    swMemoryPool *pool = worker->pool_input;
    swPackage package;

    package.length = 0;
    while (1)
    {
        package.data = pool->alloc(pool, buffer->length);
        if (package.data == NULL)
        {
            swYield();
            swWarn("reactor memory pool full.");
            continue;
        }
        break;
    }
    task.data.info.type = SW_EVENT_PACKAGE;

    while (trunk != NULL)
    {
        task.data.info.len = trunk->length;
        memcpy(package.data + package.length, trunk->store.ptr, trunk->length);
        package.length += trunk->length;

        swBuffer_pop_trunk(buffer, trunk);
        trunk = swBuffer_get_trunk(buffer);
    }
    task.data.info.len = sizeof(package);
    task.target_worker_id = target_worker_id;
    memcpy(task.data.data, &package, sizeof(package));
    //swWarn("[ReactorThread] copy_n=%d", package.length);
    return factory->dispatch(factory, &task);

#else

    int ret;
    task.data.info.type = SW_EVENT_PACKAGE_START;
    task.target_worker_id = -1;

    /**
     * lock target
     */
    SwooleTG.factory_lock_target = 1;

    while (trunk != NULL)
    {
        task.data.info.len = trunk->length;
        memcpy(task.data.data, trunk->store.ptr, task.data.info.len);
        //package end
        if (trunk->next == NULL)
        {
            task.data.info.type = SW_EVENT_PACKAGE_END;
        }
        ret = factory->dispatch(factory, &task);
        //TODO: 处理数据失败,数据将丢失
        if (ret < 0)
        {
            swWarn("factory->dispatch() failed.");
        }
        swBuffer_pop_trunk(buffer, trunk);
        trunk = swBuffer_get_trunk(buffer);

        swTrace("send2worker[trunk_num=%d][type=%d]\n", buffer->trunk_num, _send.info.type);
    }
    /**
     * unlock
     */
    SwooleTG.factory_target_worker = -1;
    SwooleTG.factory_lock_target = 0;

#endif
    return SW_OK;
}
Exemple #4
0
int swConnection_send_string_buffer(swConnection *conn)
{
    int ret;
    swString *buffer = conn->object;
    swFactory *factory = SwooleG.factory;
    swDispatchData task;

    task.data.info.fd = conn->fd;
    task.data.info.from_id = conn->from_id;

#ifdef SW_USE_RINGBUFFER

    swServer *serv = SwooleG.serv;
    int target_worker_id = swServer_worker_schedule(serv, conn->fd);
    swWorker *worker = swServer_get_worker(serv, target_worker_id);
    swMemoryPool *pool = worker->pool_input;
    swPackage package;

    package.length = buffer->length;
    while (1)
    {
        package.data = pool->alloc(pool, buffer->length);
        if (package.data == NULL)
        {
            swYield();
            swWarn("reactor memory pool full.");
            continue;
        }
        break;
    }
    task.data.info.type = SW_EVENT_PACKAGE;
    task.data.info.len = sizeof(package);
    task.target_worker_id = target_worker_id;
    //swoole_dump_bin(package.data, 's', buffer->length);
    memcpy(package.data, buffer->str, buffer->length);
    memcpy(task.data.data, &package, sizeof(package));
    ret = factory->dispatch(factory, &task);

#else
    int send_n = buffer->length;
    task.data.info.type = SW_EVENT_PACKAGE_START;
    task.target_worker_id = -1;

    /**
     * lock target
     */
    SwooleTG.factory_lock_target = 1;

    void *send_ptr = buffer->str;
    do
    {
        if (send_n > SW_BUFFER_SIZE)
        {
            task.data.info.len = SW_BUFFER_SIZE;
            memcpy(task.data.data, send_ptr, SW_BUFFER_SIZE);
        }
        else
        {
            task.data.info.type = SW_EVENT_PACKAGE_END;
            task.data.info.len = send_n;
            memcpy(task.data.data, send_ptr, send_n);
        }

        swTrace("dispatch, type=%d|len=%d\n", _send.info.type, _send.info.len);

        ret = factory->dispatch(factory, &task);
        //TODO: 处理数据失败,数据将丢失
        if (ret < 0)
        {
            swWarn("factory->dispatch failed.");
        }
        send_n -= task.data.info.len;
        send_ptr += task.data.info.len;
    }
    while (send_n > 0);

    /**
     * unlock
     */
    SwooleTG.factory_target_worker = -1;
    SwooleTG.factory_lock_target = 0;

#endif
    return ret;
}