示例#1
0
/**
 * dispatch
 */
int swProcessPool_dispatch(swProcessPool *pool, swEventData *data, int worker_id)
{
	//no worker_id, will round
	if(worker_id < 0)
	{
		worker_id = (pool->round_id++)%pool->worker_num;
	}
	swWorker *worker = &swProcessPool_worker(pool, worker_id);
	return swWrite(worker->pipe_master, data, sizeof(data->info) + data->info.len);
}
示例#2
0
/**
 * 主进程向worker进程发送数据
 * @param worker_id 发到指定的worker进程
 */
int swFactoryProcess_send2worker(swFactory *factory, swEventData *data, int worker_id)
{
	swFactoryProcess *object = factory->object;
	swServer *serv = factory->ptr;
	int pti;
	int ret;
	int send_len = sizeof(data->info) + data->info.len;

	if (worker_id < 0)
	{
		//轮询
		// data->info.from_id > serv->poll_thread_num, UDP必须使用轮询
		if (serv->dispatch_mode == SW_DISPATCH_ROUND || data->info.from_id > serv->poll_thread_num)
		{
			pti = (object->worker_pti++) % object->worker_num;
		}
		//使用fd取摸来散列
		else if (serv->dispatch_mode == SW_DISPATCH_FDMOD)
		{
			pti = data->info.fd % object->worker_num;
		}
		//使用抢占式队列(IPC消息队列)分配
		else
		{
#if SW_WORKER_IPC_MODE != 2
			swError("SW_DISPATCH_QUEUE must use (SW_WORKER_IPC_MODE = 2)");
#endif
			//msgsnd参数必须>0
			//worker进程中正确的mtype应该是pti + 1
			pti = object->worker_num;
		}
	}
	//指定了worker_id
	else
	{
		pti = worker_id;
	}

#if SW_WORKER_IPC_MODE == 2
	//insert to msg queue
	swQueue_data *in_data = (swQueue_data *)((void *)data - sizeof(long));

	//加1防止id为0的worker进程出错
	in_data->mtype = pti + 1;

	swDataHead *info = (swDataHead *)in_data->mdata;
	ret = object->rd_queue.in(&object->rd_queue, in_data, send_len);
	swTrace("[Master]rd_queue[%ld]->in: fd=%d|type=%d|len=%d", in_data->mtype, info->fd, info->type, info->len);
#else
	//send to unix sock
	ret = swWrite(object->workers[pti].pipe_master, (char *) data, send_len);
#endif
	return ret;
}
示例#3
0
/**
 * 主进程向worker进程发送数据
 * @param worker_id 发到指定的worker进程
 */
int swFactoryProcess_send2worker(swFactory *factory, swEventData *data, int worker_id)
{
	swFactoryProcess *object = factory->object;
	swServer *serv = factory->ptr;
	int pti = 0;
	int ret;
	int send_len = sizeof(data->info) + data->info.len;

	if (worker_id < 0)
	{
		if (SwooleTG.factory_lock_target)
		{
			if (SwooleTG.factory_target_worker < 0)
			{
				pti = swFactoryProcess_schedule(object, data);
				SwooleTG.factory_target_worker = pti;
			}
			else
			{
				pti = SwooleTG.factory_target_worker;
			}
		}
		else
		{
			pti = swFactoryProcess_schedule(object, data);
		}
	}
	//指定了worker_id
	else
	{
		pti = worker_id;
	}

	if (serv->ipc_mode == SW_IPC_MSGQUEUE)
	{
		//insert to msg queue
		swQueue_data *in_data = (swQueue_data *) ((void *) data - sizeof(long));

		//加1防止id为0的worker进程出错
		in_data->mtype = pti + 1;
		ret = object->rd_queue.in(&object->rd_queue, in_data, send_len);
		//swTrace("[Master]rd_queue[%ld]->in: fd=%d|type=%d|len=%d", in_data->mtype, info->fd, info->type, info->len);
	}
	else
	{
		//send to unix sock
		//swWarn("pti=%d|from_id=%d|data_len=%d|swDataHead_size=%ld", pti, data->info.from_id, send_len, sizeof(swDataHead));
		ret = swWrite(object->workers[pti].pipe_master, (void *) data, send_len);
	}
	return ret;
}
示例#4
0
int swFactoryProcess_event(swFactory *factory, int controller_id, swEventData *data)
{
	swFactoryProcess *object = factory->object;
	int pipe_fd, ret;
	int send_len = sizeof(data->info) + data->info.len;

	//这是一个controller
	if(controller_id > manager_controller_count)
	{
		swWarn("controller_id > manager_controller_count");
		return SW_ERR;
	}
	pipe_fd = manager_controller_pipes[controller_id].pipes[0];
	ret = swWrite(pipe_fd, (char *)data, send_len);
	return (ret < 0) ? SW_ERR : SW_OK;
}
示例#5
0
int swFactoryProcess_dispatch(swFactory *factory, swEventData *data)
{
	swFactoryProcess *this = factory->object;
	int pti = this->worker_pti;
	int ret;

	if (this->worker_pti >= this->worker_num)
	{
		this->worker_pti = 0;
		pti = 0;
	}
	swTrace("[ReadThread]sendto: pipe=%d|worker=%d\n", this->workers[pti].pipe_fd, pti);
	//send to unix sock
	ret = swWrite(this->workers[pti].pipe_fd, (char *) data, data->len + (3 * sizeof(int)));
	if (ret < 0)
	{
		return SW_ERR;
	}
	this->worker_pti++;
	return SW_OK;
}
示例#6
0
/**
 * dispatch
 */
int swProcessPool_dispatch(swProcessPool *pool, swEventData *data)
{
	int id = (pool->round_id++)%pool->worker_num;
	swWorker *worker = &swProcessPool_worker(pool, id);
	return swWrite(worker->pipe_master, data, sizeof(data->info) + data->info.len);
}
示例#7
0
/**
 * 主进程向worker进程发送数据
 * @param worker_id 发到指定的worker进程
 */
int swFactoryProcess_send2worker(swFactory *factory, swEventData *data, int worker_id)
{
	swFactoryProcess *object = factory->object;
	swServer *serv = factory->ptr;
	int pti = 0;
	int ret;
	int send_len = sizeof(data->info) + data->info.len;

	if (worker_id < 0)
	{
		//轮询
		if (serv->dispatch_mode == SW_DISPATCH_ROUND)
		{
			pti = (object->worker_pti++) % object->worker_num;
		}
		//使用fd取摸来散列
		else if (serv->dispatch_mode == SW_DISPATCH_FDMOD)
		{
			//Fixed #48. 替换一下顺序
			//udp use remote port
			if (data->info.type == SW_EVENT_UDP)
			{
				pti = ((uint16_t) data->info.from_id) % object->worker_num;
			}
			else
			{
				pti = data->info.fd % object->worker_num;
			}
		}
		//使用抢占式队列(IPC消息队列)分配
		else
		{
#if SW_WORKER_IPC_MODE == 2
			//msgsnd参数必须>0
			//worker进程中正确的mtype应该是pti + 1
			pti = object->worker_num;
#else
			int i;
			atomic_t *round = &SwooleWG.worker_pti;
			for(i=0; i< serv->worker_num; i++)
			{
				sw_atomic_fetch_add(round, 1);
				pti = (*round) % serv->worker_num;
				if (object->workers_status[pti] == SW_WORKER_IDLE)
				{
					break;
				}
			}
#endif
		}
	}
	//指定了worker_id
	else
	{
		pti = worker_id;
	}

#if SW_WORKER_IPC_MODE == 2
	//insert to msg queue
	swQueue_data *in_data = (swQueue_data *)((void *)data - sizeof(long));

	//加1防止id为0的worker进程出错
	in_data->mtype = pti + 1;

	swDataHead *info = (swDataHead *)in_data->mdata;
	ret = object->rd_queue.in(&object->rd_queue, in_data, send_len);
	swTrace("[Master]rd_queue[%ld]->in: fd=%d|type=%d|len=%d", in_data->mtype, info->fd, info->type, info->len);
#else
	//swWarn("pti=%d|from_id=%d", pti, data->info.from_id);
	//send to unix sock
	ret = swWrite(object->workers[pti].pipe_master, (char *) data, send_len);
#endif
	return ret;
}
示例#8
0
/**
 * Send the task result to worker
 */
int swTaskWorker_finish(swServer *serv, char *data, int data_len)
{
    swEventData buf;
    if (SwooleG.task_worker_num < 1)
    {
        swWarn("cannot use task/finish, because no set serv->task_worker_num.");
        return SW_ERR;
    }

    int ret;
    //for swoole_server_task
    if (current_task->info.type == SW_TASK_NONBLOCK)
    {
        buf.info.type = SW_EVENT_FINISH;
        buf.info.fd = current_task->info.fd;

        //write to file
        if (data_len >= sizeof(buf.data))
        {
            if (swTaskWorker_large_pack(&buf, data, data_len) < 0 )
            {
                swWarn("large task pack failed()");
                return SW_ERR;
            }
        }
        else
        {
            memcpy(buf.data, data, data_len);
            buf.info.len = data_len;
            buf.info.from_fd = 0;
        }

        //tasking

        /**
         * TODO: 这里需要重构,改成统一的模式
         */
        if (serv->factory_mode == SW_MODE_PROCESS)
        {
            ret = swServer_send2worker_blocking(serv, &buf, sizeof(buf.info) + buf.info.len, current_task->info.from_id);
        }
        else
        {
            ret = swWrite(SwooleG.event_workers->workers[current_task->info.from_id].pipe_worker, &buf, sizeof(buf.info) + data_len);
        }
    }
    else
    {
        uint64_t flag = 1;
        uint16_t worker_id = current_task->info.from_id;

        /**
         * Use worker shm store the result
         */
        swEventData *result = &(SwooleG.task_result[worker_id]);
        swPipe *task_notify_pipe = &(SwooleG.task_notify[worker_id]);

        result->info.type = SW_EVENT_FINISH;
        result->info.fd = current_task->info.fd;

        if (data_len >= sizeof(buf.data))
        {
            if (swTaskWorker_large_pack(result, data, data_len) < 0)
            {
                swWarn("large task pack failed()");
                return SW_ERR;
            }
        }
        else
        {
            memcpy(result->data, data, data_len);
            result->info.len = data_len;
            result->info.from_fd = 0;
        }

        while (1)
        {
            ret = task_notify_pipe->write(task_notify_pipe, &flag, sizeof(flag));
            if (ret < 0 && errno == EAGAIN)
            {
                if (swSocket_wait(task_notify_pipe->getFd(task_notify_pipe, 1), -1, SW_EVENT_WRITE) == 0)
                {
                    continue;
                }
            }
            break;
        }
    }
    if (ret < 0)
    {
        swWarn("TaskWorker: send result to worker failed. Error: %s[%d]", strerror(errno), errno);
    }
    return ret;
}
示例#9
0
int swServer_onFinish(swFactory *factory, swSendData *resp)
{
	return swWrite(resp->fd, resp->data, resp->len);
}
示例#10
0
/**
 * send to client or append to out_buffer
 */
int swReactorThread_send(swEventData *resp)
{
	int buf_size, copy_n;
	swServer *serv = SwooleG.serv;
	swSendData send_data;
	swEvent closeFd;
	swBuffer_trunk *trunk;
	swTask_sendfile *task;

	swConnection *conn = swServer_get_connection(serv, resp->info.fd);
	swReactor *reactor = &(serv->reactor_threads[conn->from_id].reactor);

	//recv length=0, will close connection
	if (resp->info.len == 0)
	{
#ifdef SW_REACTOR_DIRECT_SEND
		close_fd:
#endif
		{
			closeFd.fd = resp->info.fd;
			closeFd.from_id = resp->info.from_id;
			closeFd.type = SW_EVENT_CLOSE;
			//printf("closeFd.fd=%d|from_id=%d\n", closeFd.fd, closeFd.from_id);
			swReactorThread_onClose(reactor, &closeFd);
		}
		return SW_OK;
	}
	//sendfile to client
	else if(resp->info.type == SW_EVENT_SENDFILE)
	{
		trunk = swConnection_get_out_buffer(conn, SW_TRUNK_SENDFILE);
		if (trunk == NULL)
		{
			swWarn("get out_buffer trunk failed.");
			return SW_ERR;
		}
		task = sw_malloc(sizeof(swTask_sendfile));
		if (task == NULL)
		{
			swWarn("malloc for swTask_sendfile failed.");
			//TODO: 回收这里的内存
			return SW_ERR;
		}
		bzero(task, sizeof(swTask_sendfile));
		int file_fd = open(resp->data, O_RDONLY);
		if (file_fd < 0)
		{
			swWarn("open file[%s] failed. Error: %s[%d]", task->filename, strerror(errno), errno);
			return SW_ERR;
		}
		struct stat file_stat;
		if (fstat(file_fd, &file_stat) < 0)
		{
			swWarn("swoole_async_readfile: fstat failed. Error: %s[%d]", strerror(errno), errno);
			return SW_ERR;
		}
		task->filesize = file_stat.st_size;
		task->fd = file_fd;
		trunk->data = (void *)task;
		reactor->set(reactor, resp->info.fd, SW_EVENT_TCP | SW_EVENT_WRITE | SW_EVENT_READ);
	}
	//send data
	else
	{
		send_data.data = resp->data;
		send_data.info.len = resp->info.len;
		send_data.info.from_id = resp->info.from_id;
		send_data.info.fd = resp->info.fd;

#ifdef SW_REACTOR_DIRECT_SEND
		if(!swBuffer_empty(conn->out_buffer))
		{
			trunk = swBuffer_get_trunk(conn->out_buffer);
#else
		{
			trunk = swConnection_get_out_buffer(conn, SW_TRUNK_DATA);
#endif
			buf_size = conn->out_buffer->trunk_size - trunk->length;

#ifdef SW_REACTOR_DIRECT_SEND
			append_out_buffer:
#else
			//listen EPOLLOUT event
			reactor->set(reactor, resp->info.fd, SW_EVENT_TCP | SW_EVENT_WRITE | SW_EVENT_READ);
#endif
			do
			{
				copy_n =  (buf_size >= send_data.info.len) ? send_data.info.len : buf_size;
				memcpy(trunk->data, send_data.data, copy_n);
				send_data.data += copy_n;
				send_data.info.len -= copy_n;
				trunk->length += copy_n;
				buf_size += copy_n;

				//trunk is full, create new trunk
				if (trunk->length == conn->out_buffer->trunk_size)
				{
					//trunk no enough space, creating a new trunk
					trunk = swBuffer_new_trunk(conn->out_buffer, SW_TRUNK_DATA);
					if (trunk == NULL)
					{
						swWarn("append to out_buffer failed.");
						return SW_ERR;
					}
					buf_size = conn->out_buffer->trunk_size;
				}
			} while(send_data.info.len > 0);
		}
#ifdef SW_REACTOR_DIRECT_SEND
		else
		{
			//try send
			int ret = swWrite(send_data.info.fd, send_data.data, send_data.info.len);
			if (ret < 0)
			{
				//连接已被关闭
				if (errno == ECONNRESET || errno == EBADF)
				{
					goto close_fd;
				}
				swWarn("factory->onFinish failed.fd=%d|from_id=%d. Error: %s[%d]", resp->info.fd, resp->info.from_id, strerror(errno), errno);
			}
			//Did not finish, add to writable event callback
			else if(ret < resp->info.len)
			{
				trunk = swConnection_get_out_buffer(conn, SW_TRUNK_DATA);
				send_data.data += ret;
				send_data.info.len -= ret;
				buf_size = conn->out_buffer->trunk_size;
				goto append_out_buffer;
			}
			//printf("[writer]pop.fd=%d|from_id=%d|data=%s\n", resp->info.fd, resp->info.from_id, resp->data);
		}
#endif
	}